From 43afb84e1e4e31136994c7bf3941465c43cd8616 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Wed, 20 Sep 2023 11:05:43 +0900 Subject: [PATCH] (WebView) Set display area and Change Visual when WebView relayout Previously, we change display area after only at PropertyNotification time. It will wait until 1 frame rendered. If we change web view size by event side, the display area applied lately. This patch make we change update area when OnRelayout, so we can apply changeness more faster timing. -- And also, Let we change visual when the size of webview changed. If so, it can be reduce some flickering effect while change the udpate area. Change-Id: Ia7d6becc11160d88353f62bbdb43f75764550b67 Signed-off-by: Eunki, Hong --- .../internal/controls/web-view/web-view-impl.cpp | 175 ++++++++++++++++----- .../internal/controls/web-view/web-view-impl.h | 18 +++ 2 files changed, 152 insertions(+), 41 deletions(-) mode change 100755 => 100644 dali-toolkit/internal/controls/web-view/web-view-impl.cpp diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp old mode 100755 new mode 100644 index a92c4bb..987f297 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.cpp +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.cpp @@ -16,10 +16,9 @@ */ // CLASS HEADER -#include "web-view-impl.h" +#include // EXTERNAL INCLUDES -#include #include #include #include @@ -44,9 +43,11 @@ #include #include #include +#include +#include #include -#include #include +#include #include #include @@ -95,6 +96,57 @@ std::unordered_map>& static std::unordered_map> pluginWebViewMap; return pluginWebViewMap; } + +enum class DisplayAreaCalculateOption +{ + PROPERTY = 0, ///< Calculate display update area by property + CURRENT_PROPERTY = 1, ///< Calculate display update area by current property +}; + +/** + * @brief Helper function to calculate exact display area, offset and size. + * It will be useful when view size is not integer value, or view size is not matched with texture size. + * + * @param[in] self The view itself. + * @param[in] option Option of this calculation. Let we decide what kind of property will be used. + * @return DisplayArea for this view. + */ +Rect CalculateDisplayArea(Dali::Actor self, DisplayAreaCalculateOption option) +{ + bool positionUsesAnchorPoint = self.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT); + Vector3 actorSize = (option == DisplayAreaCalculateOption::CURRENT_PROPERTY) ? self.GetCurrentProperty(Actor::Property::SIZE) * self.GetCurrentProperty(Actor::Property::SCALE) + : self.GetProperty(Actor::Property::SIZE) * self.GetProperty(Actor::Property::SCALE); + Vector3 anchorPointOffSet = actorSize * (positionUsesAnchorPoint ? self.GetCurrentProperty(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT); + Vector2 screenPosition = (option == DisplayAreaCalculateOption::CURRENT_PROPERTY) ? self.GetProperty(Actor::Property::SCREEN_POSITION) + : Dali::DevelActor::CalculateScreenPosition(self); + + Dali::Rect displayArea; + displayArea.x = screenPosition.x - anchorPointOffSet.x; + displayArea.y = screenPosition.y - anchorPointOffSet.y; + displayArea.width = actorSize.x; + displayArea.height = actorSize.y; + + return displayArea; +} + +constexpr Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); + +/** + * @brief Helper function to calculate exact pixel area value by view and texture size. + * It will be useful when view size is not integer value, or view size is not matched with texture size. + * + * @param[in] viewSize The size of view. + * @param[in] textureWidth The width of texture, that must be integer type. + * @param[in] textureHeight The height of texture, that must be integer type. + * @return PixelArea value that image visual can use. + */ +Vector4 CalculatePixelArea(const Size& viewSize, const uint32_t textureWidth, const uint32_t textureHeight) +{ + float widthRatio = textureWidth == 0u ? 1.0f : viewSize.width / static_cast(textureWidth); + float heightRatio = textureHeight == 0u ? 1.0f : viewSize.height / static_cast(textureHeight); + return Vector4(0.0f, 0.0f, widthRatio, heightRatio); +} + } // namespace WebView::WebView(const std::string& locale, const std::string& timezoneId) @@ -102,10 +154,13 @@ WebView::WebView(const std::string& locale, const std::string& timezoneId) mVisual(), mWebViewSize(Stage::GetCurrent().GetSize()), mWebEngine(), + mLastRenderedNativeImageWidth(0u), + mLastRenderedNativeImageHeight(0u), mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height), mVideoHoleEnabled(false), mMouseEventsEnabled(true), mKeyEventsEnabled(true), + mVisualChangeRequired(false), mScreenshotCapturedCallback{nullptr}, mFrameRenderedCallback{nullptr} { @@ -123,10 +178,13 @@ WebView::WebView(uint32_t argc, char** argv) mVisual(), mWebViewSize(Stage::GetCurrent().GetSize()), mWebEngine(), + mLastRenderedNativeImageWidth(0u), + mLastRenderedNativeImageHeight(0u), mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height), mVideoHoleEnabled(false), mMouseEventsEnabled(true), mKeyEventsEnabled(true), + mVisualChangeRequired(false), mScreenshotCapturedCallback{nullptr}, mFrameRenderedCallback{nullptr} { @@ -149,7 +207,7 @@ WebView::~WebView() if(mWebEngine) { auto iter = GetPluginWebViewTable().find(mWebEngine.GetPlugin()); - if (iter != GetPluginWebViewTable().end()) + if(iter != GetPluginWebViewTable().end()) { GetPluginWebViewTable().erase(iter); } @@ -161,7 +219,7 @@ Toolkit::WebView WebView::New() { WebView* impl = new WebView(); Toolkit::WebView handle = Toolkit::WebView(*impl); - if (impl->GetPlugin()) + if(impl->GetPlugin()) { GetPluginWebViewTable()[impl->GetPlugin()] = handle; } @@ -173,7 +231,7 @@ Toolkit::WebView WebView::New(const std::string& locale, const std::string& time { WebView* impl = new WebView(locale, timezoneId); Toolkit::WebView handle = Toolkit::WebView(*impl); - if (impl->GetPlugin()) + if(impl->GetPlugin()) { GetPluginWebViewTable()[impl->GetPlugin()] = handle; } @@ -185,7 +243,7 @@ Toolkit::WebView WebView::New(uint32_t argc, char** argv) { WebView* impl = new WebView(argc, argv); Toolkit::WebView handle = Toolkit::WebView(*impl); - if (impl->GetPlugin()) + if(impl->GetPlugin()) { GetPluginWebViewTable()[impl->GetPlugin()] = handle; } @@ -196,7 +254,7 @@ Toolkit::WebView WebView::New(uint32_t argc, char** argv) Toolkit::WebView WebView::FindWebView(Dali::WebEnginePlugin* plugin) { auto iter = GetPluginWebViewTable().find(plugin); - if (iter != GetPluginWebViewTable().end()) + if(iter != GetPluginWebViewTable().end()) { return iter->second.GetHandle(); } @@ -246,6 +304,18 @@ DevelControl::ControlAccessible* WebView::CreateAccessibleObject() return new WebViewAccessible(Self(), mWebEngine); } +void WebView::OnRelayout(const Vector2& size, RelayoutContainer& container) +{ + if(!mWebEngine) + { + return; + } + + auto displayArea = CalculateDisplayArea(Self(), DisplayAreaCalculateOption::PROPERTY); + + SetDisplayArea(displayArea); +} + Dali::Toolkit::WebSettings* WebView::GetSettings() const { return mWebSettings.get(); @@ -772,48 +842,44 @@ void WebView::OnFrameRendered() mFrameRenderedCallback(); } - // Make sure that mVisual is created only once. - if (mVisual) - return; - - Dali::Toolkit::ImageUrl nativeImageUrl = Dali::Toolkit::Image::GenerateUrl(mWebEngine.GetNativeImageSource()); - mVisual = Toolkit::VisualFactory::Get().CreateVisual({{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, {Toolkit::ImageVisual::Property::URL, nativeImageUrl.GetUrl()}}); - if(mVisual) + // Make sure that mVisual is created only if required. + if(mVisualChangeRequired || !mVisual) { - DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual); - EnableBlendMode(!mVideoHoleEnabled); - } -} + // Reset flag + mVisualChangeRequired = false; -void WebView::OnDisplayAreaUpdated(Dali::PropertyNotification& /*source*/) -{ - if(!mWebEngine) - return; + auto nativeImageSourcePtr = mWebEngine.GetNativeImageSource(); - Actor self(Self()); + mLastRenderedNativeImageWidth = nativeImageSourcePtr->GetWidth(); + mLastRenderedNativeImageHeight = nativeImageSourcePtr->GetHeight(); - bool positionUsesAnchorPoint = self.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT); - Vector3 actorSize = self.GetCurrentProperty(Actor::Property::SIZE) * self.GetCurrentProperty(Actor::Property::SCALE); - Vector3 anchorPointOffSet = actorSize * (positionUsesAnchorPoint ? self.GetCurrentProperty(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT); - Vector2 screenPosition = self.GetProperty(Actor::Property::SCREEN_POSITION); + Dali::Toolkit::ImageUrl nativeImageUrl = Dali::Toolkit::Image::GenerateUrl(nativeImageSourcePtr); - Dali::Rect displayArea; - displayArea.x = screenPosition.x - anchorPointOffSet.x; - displayArea.y = screenPosition.y - anchorPointOffSet.y; - displayArea.width = actorSize.x; - displayArea.height = actorSize.y; + mVisual = Toolkit::VisualFactory::Get().CreateVisual( + {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, + {Toolkit::ImageVisual::Property::URL, nativeImageUrl.GetUrl()}, + {Toolkit::ImageVisual::Property::PIXEL_AREA, FULL_TEXTURE_RECT}, + {Toolkit::ImageVisual::Property::WRAP_MODE_U, Dali::WrapMode::CLAMP_TO_EDGE}, + {Toolkit::ImageVisual::Property::WRAP_MODE_V, Dali::WrapMode::CLAMP_TO_EDGE}}); - Size displaySize = Size(displayArea.width, displayArea.height); - if(mWebViewSize != displaySize) - { - mWebViewSize = displaySize; + if(mVisual) + { + DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual); + EnableBlendMode(!mVideoHoleEnabled); + } } +} - if(mWebViewArea != displayArea) +void WebView::OnDisplayAreaUpdated(Dali::PropertyNotification& /*source*/) +{ + if(!mWebEngine) { - mWebViewArea = displayArea; - mWebEngine.UpdateDisplayArea(mWebViewArea); + return; } + + auto displayArea = CalculateDisplayArea(Self(), DisplayAreaCalculateOption::CURRENT_PROPERTY); + + SetDisplayArea(displayArea); } void WebView::OnVisibilityChanged(Actor actor, bool isVisible, Dali::DevelActor::VisibilityChange::Type type) @@ -833,6 +899,31 @@ void WebView::OnScreenshotCaptured(Dali::PixelData pixel) } } +void WebView::SetDisplayArea(const Dali::Rect& displayArea) +{ + Size displaySize = Size(displayArea.width, displayArea.height); + if(mWebViewSize != displaySize) + { + mWebViewSize = displaySize; + } + + if(mWebViewArea != displayArea) + { + // WebEngine visual size changed. we have to re-create visual. + mVisualChangeRequired = true; + + // Change old visual's pixel area matched as changed web view size + if(mVisual) + { + auto pixelArea = CalculatePixelArea(mWebViewSize, mLastRenderedNativeImageWidth, mLastRenderedNativeImageHeight); + Toolkit::GetImplementation(mVisual).DoAction(Toolkit::DevelVisual::Action::UPDATE_PROPERTY, {{Toolkit::ImageVisual::Property::PIXEL_AREA, pixelArea}}); + } + + mWebViewArea = displayArea; + mWebEngine.UpdateDisplayArea(mWebViewArea); + } +} + void WebView::OnSceneConnection(int depth) { Control::OnSceneConnection(depth); @@ -1258,7 +1349,9 @@ bool WebView::SetVisibility(bool visible) } WebView::WebViewAccessible::WebViewAccessible(Dali::Actor self, Dali::WebEngine& webEngine) -: ControlAccessible(self), mRemoteChild{}, mWebEngine{webEngine} +: ControlAccessible(self), + mRemoteChild{}, + mWebEngine{webEngine} { mRemoteChild.SetParent(this); diff --git a/dali-toolkit/internal/controls/web-view/web-view-impl.h b/dali-toolkit/internal/controls/web-view/web-view-impl.h index 0673f77..5cf24e5 100755 --- a/dali-toolkit/internal/controls/web-view/web-view-impl.h +++ b/dali-toolkit/internal/controls/web-view/web-view-impl.h @@ -443,6 +443,11 @@ private: // From Control DevelControl::ControlAccessible* CreateAccessibleObject() override; /** + * @copydoc Toolkit::Internal::Control::OnRelayout() + */ + void OnRelayout(const Vector2& size, RelayoutContainer& container) override; + + /** * @copydoc Toolkit::Control::GetNaturalSize */ Vector3 GetNaturalSize() override; @@ -678,6 +683,14 @@ private: */ void OnScreenshotCaptured(Dali::PixelData pixel); + /** + * @brief Set DisplayArea by input value. + * It will send changes area infomations to webengine internally. + * + * @param[in] displayArea The display area for current webview want to show. + */ + void SetDisplayArea(const Dali::Rect& displayArea); + protected: class WebViewAccessible : public DevelControl::ControlAccessible { @@ -711,6 +724,9 @@ private: Dali::Size mWebViewSize; Dali::WebEngine mWebEngine; + uint32_t mLastRenderedNativeImageWidth; + uint32_t mLastRenderedNativeImageHeight; + std::unique_ptr mWebSettings; std::unique_ptr mWebBackForwardList; @@ -722,6 +738,8 @@ private: bool mMouseEventsEnabled; bool mKeyEventsEnabled; + bool mVisualChangeRequired; + Dali::Toolkit::WebView::WebViewScreenshotCapturedCallback mScreenshotCapturedCallback; Dali::WebEnginePlugin::WebEngineFrameRenderedCallback mFrameRenderedCallback; }; -- 2.7.4