virtual void StopReading(bool alsoNonDiscardable) = 0;
/**
+ * @brief Suppresses reading of screen-reader
+ *
+ * @param suppress whether to suppress reading of screen-reader
+ */
+ virtual void SuppressScreenReader(bool suppress) = 0;
+
+ /**
* @brief Get screen reader status.
*/
virtual bool GetScreenReaderEnabled() = 0;
**/
static Bridge* GetCurrentBridge();
+ /**
+ * @brief Blocks auto-initialization of AT-SPI bridge
+ *
+ * Use this only if your application starts before DBus does, and call it early in main()
+ * (before GetCurrentBridge() is called by anyone). GetCurrentBridge() will then return an
+ * instance of DummyBridge.
+ *
+ * When DBus is ready, call EnableAutoInit(). Please note that GetCurrentBridge() may still
+ * return an instance of DummyBridge if AT-SPI was disabled at compile time or using an
+ * environment variable, or if creating the real bridge failed.
+ *
+ * @see Dali::Accessibility::DummyBridge
+ * @see Dali::Accessibility::Bridge::EnableAutoInit
+ */
+ static void DisableAutoInit();
+
+ /**
+ * @brief Re-enables auto-initialization of AT-SPI bridge
+ *
+ * @param topLevelWindow Accessible object for Scene::GetRootLayer()
+ * @param applicationName Application name
+ *
+ * Normal applications do not have to call this function. GetCurrentBridge() tries to
+ * initialize the AT-SPI bridge when it is called for the first time.
+ *
+ * @see Dali::Accessibility::Bridge::DisableAutoInit
+ * @see Dali::Accessibility::Bridge::AddTopLevelWindow
+ * @see Dali::Accessibility::Bridge::SetApplicationName
+ */
+ static void EnableAutoInit(Accessible* topLevelWindow, const std::string& applicationName);
+
protected:
struct Data
{
std::shared_ptr<Data> data;
friend class Accessible;
+ enum class AutoInitState
+ {
+ DISABLED,
+ ENABLED
+ };
+ inline static AutoInitState autoInitState = AutoInitState::ENABLED;
+
/**
* @brief Registers accessible object to be known in bridge object
*
}
}
+bool Dali::AtspiAccessibility::SuppressScreenReader(bool suppress)
+{
+ if(auto bridge = Dali::Accessibility::Bridge::GetCurrentBridge())
+ {
+ bridge->SuppressScreenReader(suppress);
+ return true;
+ }
+
+ return false;
+}
+
void Dali::AtspiAccessibility::Say(const std::string& text, bool discardable, std::function<void(std::string)> callback)
{
if(auto bridge = Dali::Accessibility::Bridge::GetCurrentBridge())
DALI_ADAPTOR_API void StopReading(bool alsoNonDiscardable = false);
/**
+ * @brief Suppresses reading of screen-reader
+ *
+ * @param suppress whether to suppress reading of screen-reader
+ * @return true on success, false otherwise
+ */
+DALI_ADAPTOR_API bool SuppressScreenReader(bool suppress);
+
+/**
* @brief Set ATSPI to be turned On or Off forcibly.
*
* @param[in] turnOn true to turn on, false to turn off.
/**
* @brief Drawable is a object class for drawing a vector primitive.
*/
-class CanvasRenderer::Drawable : public BaseHandle
+class DALI_ADAPTOR_API CanvasRenderer::Drawable : public BaseHandle
{
public:
/**
using WebEngineFrameRenderedSignalType = Signal<void(void)>;
/**
- * @brief WebView signal type related with policy would be decided.
+ * @brief WebView signal type related with response policy would be decided.
*/
- using WebEnginePolicyDecisionSignalType = Signal<void(std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
+ using WebEngineResponsePolicyDecisionSignalType = Signal<void(std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
/**
* @brief Hit test callback called after hit test is created asynchronously.
virtual WebEngineConsoleMessageSignalType& ConsoleMessageSignal() = 0;
/**
- * @brief Connect to this signal to be notified when new policy would be decided.
+ * @brief Connect to this signal to be notified when response policy would be decided.
*
* @return A signal object to connect with.
*/
- virtual WebEnginePolicyDecisionSignalType& PolicyDecisionSignal() = 0;
+ virtual WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal() = 0;
/**
* @brief Connect to this signal to be notified when certificate need be confirmed.
return GetImplementation(*this).ConsoleMessageSignal();
}
-Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& WebEngine::PolicyDecisionSignal()
+Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& WebEngine::ResponsePolicyDecisionSignal()
{
- return GetImplementation(*this).PolicyDecisionSignal();
+ return GetImplementation(*this).ResponsePolicyDecisionSignal();
}
Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::CertificateConfirmSignal()
Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& ConsoleMessageSignal();
/**
- * @brief Connect to this signal to be notified when new policy would be decided.
+ * @brief Connect to this signal to be notified when response policy would be decided.
*
* @return A signal object to connect with.
*/
- Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& PolicyDecisionSignal();
+ Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal();
/**
* @brief Connect to this signal to be notified when certificate need be confirmed.
describedByObject};
}
+void BridgeAccessible::SuppressScreenReader(bool suppress)
+{
+ suppressScreenReader = suppress;
+}
+
DBus::ValueOrError<bool> BridgeAccessible::DoGesture(Dali::Accessibility::Gesture type, int32_t xBeg, int32_t yBeg, int32_t xEnd, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime)
{
return FindSelf()->DoGesture(Dali::Accessibility::GestureInfo{type, xBeg, xEnd, yBeg, yEnd, state, eventTime});
}
DBus::ValueOrError<std::unordered_map<std::string, std::string>> BridgeAccessible::GetAttributes()
{
- return FindSelf()->GetAttributes();
+ std::unordered_map<std::string, std::string> attributes = FindSelf()->GetAttributes();
+ if(suppressScreenReader)
+ {
+ attributes.insert({"suppress-screen-reader", "true"});
+ }
+
+ return attributes;
}
DBus::ValueOrError<std::vector<std::string>> BridgeAccessible::GetInterfaces()
{
BridgeAccessible();
void RegisterInterfaces();
+ bool suppressScreenReader = false;
public:
enum class GetNeighborSearchMode
>;
ReadingMaterialType GetReadingMaterial();
+ void SuppressScreenReader(bool) override;
DBus::ValueOrError<bool> DoGesture(Dali::Accessibility::Gesture type, int32_t xBeg, int32_t yBeg, int32_t xEnd, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime);
}
};
+static bool bridgeInitialized;
+
static Bridge* CreateBridge()
{
+ bridgeInitialized = true;
+
try
{
/* check environment variable first */
Bridge* Bridge::GetCurrentBridge()
{
- static Bridge* bridge = CreateBridge();
- return bridge;
+ static Bridge* bridge;
+
+ if (bridge)
+ {
+ return bridge;
+ }
+ else if (autoInitState == AutoInitState::ENABLED)
+ {
+ bridge = CreateBridge();
+ return bridge;
+ }
+
+ return Dali::Accessibility::DummyBridge::GetInstance();
+}
+
+void Bridge::DisableAutoInit()
+{
+ if (bridgeInitialized)
+ {
+ DALI_LOG_ERROR("Bridge::DisableAutoInit() called after bridge auto-initialization");
+ }
+
+ autoInitState = AutoInitState::DISABLED;
+}
+
+void Bridge::EnableAutoInit(Accessible* topLevelWindow, const std::string& applicationName)
+{
+ autoInitState = AutoInitState::ENABLED;
+
+ if (bridgeInitialized)
+ {
+ return;
+ }
+
+ auto* bridge = Bridge::GetCurrentBridge();
+ bridge->AddTopLevelWindow(topLevelWindow);
+ bridge->SetApplicationName(applicationName);
+ bridge->Initialize();
}
return Accessibility::DummyBridge::GetInstance();
}
+void Accessibility::Bridge::DisableAutoInit()
+{
+}
+
+void Accessibility::Bridge::EnableAutoInit(Accessible*, const std::string&)
+{
+}
+
void Accessibility::Accessible::EmitStateChanged(Accessibility::State state, int newValue1, int newValue2)
{
}
{
}
+ void SuppressScreenReader(bool suppress) override
+ {
+ }
+
bool GetScreenReaderEnabled() override
{
return false;
+++ /dev/null
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <dali/internal/canvas-renderer/common/canvas-renderer-factory.h>
-#include <dali/internal/canvas-renderer/common/canvas-renderer-impl.h>
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Adaptor
-{
-namespace CanvasRendererFactory
-{
-__attribute__((weak)) Dali::Internal::Adaptor::CanvasRenderer* New(const Vector2& viewBox)
-{
- return new Internal::Adaptor::CanvasRenderer();
-}
-
-} // namespace CanvasRendererFactory
-
-} // namespace Adaptor
-
-} // namespace Internal
-
-} // namespace Dali
+++ /dev/null
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <dali/internal/canvas-renderer/common/drawable-factory.h>
-#include <dali/internal/canvas-renderer/common/drawable-impl.h>
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Adaptor
-{
-namespace DrawableFactory
-{
-__attribute__((weak)) Dali::Internal::Adaptor::Drawable* New()
-{
- return new Internal::Adaptor::Drawable();
-}
-
-} // namespace DrawableFactory
-
-} // namespace Adaptor
-
-} // namespace Internal
-
-} // namespace Dali
+++ /dev/null
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <dali/internal/canvas-renderer/common/shape-factory.h>
-#include <dali/internal/canvas-renderer/common/shape-impl.h>
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Adaptor
-{
-namespace ShapeFactory
-{
-__attribute__((weak)) Dali::Internal::Adaptor::Shape* New()
-{
- // default implementation returns 'dummy'.
- return new Internal::Adaptor::Shape();
-}
-
-} // namespace ShapeFactory
-
-} // namespace Adaptor
-
-} // namespace Internal
-
-} // namespace Dali
# module: canvas-renderer, backend: generic (android, macos, window)
SET( adaptor_canvas_renderer_generic_src_files
- ${adaptor_canvas_renderer_dir}/common/canvas-renderer-factory.cpp
${adaptor_canvas_renderer_dir}/common/canvas-renderer-impl.cpp
${adaptor_canvas_renderer_dir}/generic/canvas-renderer-factory-generic.cpp
${adaptor_canvas_renderer_dir}/generic/canvas-renderer-impl-generic.cpp
- ${adaptor_canvas_renderer_dir}/common/drawable-factory.cpp
${adaptor_canvas_renderer_dir}/common/drawable-impl.cpp
${adaptor_canvas_renderer_dir}/generic/drawable-factory-generic.cpp
${adaptor_canvas_renderer_dir}/generic/drawable-impl-generic.cpp
- ${adaptor_canvas_renderer_dir}/common/shape-factory.cpp
${adaptor_canvas_renderer_dir}/common/shape-impl.cpp
${adaptor_canvas_renderer_dir}/generic/shape-factory-generic.cpp
${adaptor_canvas_renderer_dir}/generic/shape-impl-generic.cpp
# module: canvas-renderer, backend: ubuntu
SET( adaptor_canvas_renderer_ubuntu_src_files
- ${adaptor_canvas_renderer_dir}/common/canvas-renderer-factory.cpp
${adaptor_canvas_renderer_dir}/common/canvas-renderer-impl.cpp
${adaptor_canvas_renderer_dir}/ubuntu/canvas-renderer-factory-ubuntu.cpp
${adaptor_canvas_renderer_dir}/ubuntu/canvas-renderer-impl-ubuntu.cpp
- ${adaptor_canvas_renderer_dir}/common/drawable-factory.cpp
${adaptor_canvas_renderer_dir}/common/drawable-impl.cpp
${adaptor_canvas_renderer_dir}/ubuntu/drawable-factory-ubuntu.cpp
${adaptor_canvas_renderer_dir}/ubuntu/drawable-impl-ubuntu.cpp
- ${adaptor_canvas_renderer_dir}/common/shape-factory.cpp
${adaptor_canvas_renderer_dir}/common/shape-impl.cpp
${adaptor_canvas_renderer_dir}/ubuntu/shape-factory-ubuntu.cpp
${adaptor_canvas_renderer_dir}/ubuntu/shape-impl-ubuntu.cpp
# module: canvas-renderer, backend: tizen (generic, ivi, mobile, tizen-post, tv, wearable)
SET( adaptor_canvas_renderer_tizen_src_files
- ${adaptor_canvas_renderer_dir}/common/canvas-renderer-factory.cpp
${adaptor_canvas_renderer_dir}/common/canvas-renderer-impl.cpp
${adaptor_canvas_renderer_dir}/tizen/canvas-renderer-factory-tizen.cpp
${adaptor_canvas_renderer_dir}/tizen/canvas-renderer-impl-tizen.cpp
- ${adaptor_canvas_renderer_dir}/common/drawable-factory.cpp
${adaptor_canvas_renderer_dir}/common/drawable-impl.cpp
${adaptor_canvas_renderer_dir}/tizen/drawable-factory-tizen.cpp
${adaptor_canvas_renderer_dir}/tizen/drawable-impl-tizen.cpp
- ${adaptor_canvas_renderer_dir}/common/shape-factory.cpp
${adaptor_canvas_renderer_dir}/common/shape-impl.cpp
${adaptor_canvas_renderer_dir}/tizen/shape-factory-tizen.cpp
${adaptor_canvas_renderer_dir}/tizen/shape-impl-tizen.cpp
CanvasRendererTizen::~CanvasRendererTizen()
{
#ifdef THORVG_SUPPORT
- for(DrawableVectorIterator it = mDrawables.begin(),
- endIt = mDrawables.end();
- it != endIt;
- ++it)
+ for(auto& it : mDrawables)
{
- Dali::CanvasRenderer::Drawable drawable = (*it).GetHandle();
+ Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
if(DALI_UNLIKELY(!drawable))
{
continue;
#ifdef THORVG_SUPPORT
bool changed = false;
- for(DrawableVectorIterator it = mDrawables.begin(),
- endIt = mDrawables.end();
- it != endIt;
- ++it)
+ for(auto& it : mDrawables)
{
- Dali::CanvasRenderer::Drawable drawable = (*it).GetHandle();
+ Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
if(DALI_UNLIKELY(!drawable))
{
continue;
DALI_LOG_ERROR("ThorVG Draw fail [%p]\n", this);
return false;
}
+
+ mTvgCanvas->sync();
+
return true;
#else
return false;
bool CanvasRendererTizen::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
{
#ifdef THORVG_SUPPORT
- bool exist = false;
- for(DrawableVectorIterator it = mDrawables.begin(),
- endIt = mDrawables.end();
- it != endIt;
- ++it)
+ for(auto& it : mDrawables)
{
- if((*it) == drawable)
+ if(it.GetHandle() == drawable)
{
- exist = true;
- break;
+ DALI_LOG_ERROR("Already added [%p]\n", this);
+ return false;
}
}
- if(exist)
- {
- DALI_LOG_ERROR("Already added [%p]\n", this);
- return false;
- }
Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
tvg::Paint* pDrawable = static_cast<tvg::Paint*>(drawableImpl.GetObject());
return;
}
- mTvgCanvas->sync();
-
mTvgCanvas->target(reinterpret_cast<uint32_t*>(pBuffer), size.width, size.width, size.height, tvg::SwCanvas::ABGR8888);
#endif
}
CanvasRendererUbuntu::~CanvasRendererUbuntu()
{
#ifdef THORVG_SUPPORT
- for(DrawableVectorIterator it = mDrawables.begin(),
- endIt = mDrawables.end();
- it != endIt;
- ++it)
+ for(auto& it : mDrawables)
{
- Dali::CanvasRenderer::Drawable drawable = (*it).GetHandle();
+ Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
if(DALI_UNLIKELY(!drawable))
{
continue;
#ifdef THORVG_SUPPORT
bool changed = false;
- for(DrawableVectorIterator it = mDrawables.begin(),
- endIt = mDrawables.end();
- it != endIt;
- ++it)
+ for(auto& it : mDrawables)
{
- Dali::CanvasRenderer::Drawable drawable = (*it).GetHandle();
+ Dali::CanvasRenderer::Drawable drawable = it.GetHandle();
if(DALI_UNLIKELY(!drawable))
{
continue;
DALI_LOG_ERROR("ThorVG Draw fail [%p]\n", this);
return false;
}
+
+ mTvgCanvas->sync();
+
return true;
#else
return false;
bool CanvasRendererUbuntu::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
{
#ifdef THORVG_SUPPORT
- bool exist = false;
- for(DrawableVectorIterator it = mDrawables.begin(),
- endIt = mDrawables.end();
- it != endIt;
- ++it)
+ for(auto& it : mDrawables)
{
- if((*it) == drawable)
+ if(it.GetHandle() == drawable)
{
- exist = true;
- break;
+ DALI_LOG_ERROR("Already added [%p]\n", this);
+ return false;
}
}
- if(exist)
- {
- DALI_LOG_ERROR("Already added [%p]\n", this);
- return false;
- }
Internal::Adaptor::Drawable& drawableImpl = GetImplementation(drawable);
tvg::Paint* pDrawable = static_cast<tvg::Paint*>(drawableImpl.GetObject());
return;
}
- mTvgCanvas->sync();
-
mTvgCanvas->target(reinterpret_cast<uint32_t*>(pBuffer), size.width, size.width, size.height, tvg::SwCanvas::ABGR8888);
#endif
}
*
* Temporarily holds the old GL abstractions whilst dali-core is migrated to the new API.
*/
-DALI_IMPORT_API class EglGraphicsController : public Graphics::Controller
+class EglGraphicsController : public Graphics::Controller
{
public:
/**
{
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
- GLint majorVersion, minorVersion;
- glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
- glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
- mGlesVersion = majorVersion * 10 + minorVersion;
+ // Only change gles version for the device that support above gles 3.0.
+ if(mGlesVersion >= INITIAL_GLES_VERSION)
+ {
+ GLint majorVersion, minorVersion;
+ glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
+ glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
+ mGlesVersion = majorVersion * 10 + minorVersion;
+ }
if(mGlesVersion >= GLES_VERSION_SUPPORT_BLEND_EQUATION_ADVANCED)
{
\r
// EXTERNAL INCLUDES\r
#include <Windows.h>\r
+\r
+// Need to undef the following constants as they are defined in one of the headers in Windows.h but used in DALi (via debug.h)\r
+#undef TRANSPARENT // Used in constants.h\r
+#undef CopyMemory // Used in dali-vector.h\r
+\r
#include <dali/integration-api/debug.h>\r
\r
// INTERNAL INCLUDES\r
// INTERNAL INCLUDES
#include <dali/internal/adaptor/common/application-impl.h>
-#include <dali/internal/system/common //widget-application-impl.h>
+#include <dali/internal/system/common/widget-application-impl.h>
#include <dali/public-api/adaptor-framework/widget-application.h>
namespace Dali
{
// The default plugin name
const char* DEFAULT_OBJECT_NAME("libdali2-vector-animation-renderer-plugin.so");
+// The rive animation plugin name
+const char* RIVE_OBJECT_NAME("libdali2-rive-animation-renderer-plugin.so");
} // namespace
{
mSharedObjectName = DEFAULT_OBJECT_NAME;
}
-
- Initialize();
}
VectorAnimationRendererPluginProxy::~VectorAnimationRendererPluginProxy()
}
}
-void VectorAnimationRendererPluginProxy::Initialize()
+void VectorAnimationRendererPluginProxy::Initialize(AnimationFormat format)
{
+ // initialization should be once
+ if(mPlugin)
+ {
+ return;
+ }
+
+ if(format == AnimationFormat::RIVE)
+ {
+ // for Rive
+ mSharedObjectName = RIVE_OBJECT_NAME;
+ }
+ else
+ {
+ // for Json
+ mSharedObjectName = DEFAULT_OBJECT_NAME;
+ }
+
mLibHandle = dlopen(mSharedObjectName.c_str(), RTLD_LAZY);
char* error = dlerror();
bool VectorAnimationRendererPluginProxy::Load(const std::string& url)
{
+ AnimationFormat format;
+ std::string extensionName = url.substr(url.find_last_of(".") + 1);
+ if(extensionName == "riv")
+ {
+ format = AnimationFormat::RIVE;
+ }
+ else
+ {
+ format = AnimationFormat::JSON;
+ }
+
+ Initialize(format);
+
if(mPlugin)
{
return mPlugin->Load(url);
private:
/**
+ * Vector Animation formats.
+ */
+ enum class AnimationFormat
+ {
+ NONE = 0,
+ JSON,
+ RIVE
+ };
+
+ /**
* Dynamically loads the plugin.
*/
- void Initialize();
+ void Initialize(AnimationFormat format);
private:
using CreateVectorAnimationRendererFunction = Dali::VectorAnimationRendererPlugin* (*)();
return mPlugin->ConsoleMessageSignal();
}
-Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& WebEngine::PolicyDecisionSignal()
+Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& WebEngine::ResponsePolicyDecisionSignal()
{
- return mPlugin->PolicyDecisionSignal();
+ return mPlugin->ResponsePolicyDecisionSignal();
}
Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::CertificateConfirmSignal()
Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& ConsoleMessageSignal();
/**
- @copydoc Dali::WebEngine::PolicyDecisionSignal()
+ @copydoc Dali::WebEngine::ResponsePolicyDecisionSignal()
*/
- Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& PolicyDecisionSignal();
+ Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal();
/**
* @copydoc Dali::WebEngine::CertificateConfirmSignal()
mOpaqueState(false),
mResizeEnabled(false),
mVisible(false),
- mIsRotated(false),
- mIsWindowRotated(false),
mIsTouched(false),
mIsEGLInitialized(false),
mDepth(false),
mWindowBase = windowFactory->CreateWindowBase(mPositionSize, surface, (mIsTransparent ? true : false));
mWindowBase->IconifyChangedSignal().Connect(this, &GlWindow::OnIconifyChanged);
mWindowBase->FocusChangedSignal().Connect(this, &GlWindow::OnFocusChanged);
+ mWindowBase->OutputTransformedSignal().Connect(this, &GlWindow::OnOutputTransformed);
if(Dali::Adaptor::IsAvailable())
{
}
// If window's size or position is changed, the signal will be emitted to user.
- if((needToMove) || (needToResize))
+ if(needToMove || needToResize)
{
Uint16Pair newSize(mPositionSize.width, mPositionSize.height);
Dali::GlWindow handle(this);
mResizeSignal.Emit(newSize);
+
+ if(mGlWindowRenderThread)
+ {
+ mGlWindowRenderThread->RequestWindowResize(mPositionSize.width, mPositionSize.height);
+ }
}
}
void GlWindow::OnOutputTransformed()
{
- int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
- if(screenRotationAngle != mScreenRotationAngle)
- {
- mScreenRotationAngle = screenRotationAngle;
- mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
-
- if(mTotalRotationAngle == 90 || mTotalRotationAngle == 270)
- {
- mWindowWidth = mPositionSize.height;
- mWindowHeight = mPositionSize.width;
- }
- else
- {
- mWindowWidth = mPositionSize.width;
- mWindowHeight = mPositionSize.height;
- }
+ int newScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
+ DALI_LOG_RELEASE_INFO("GlWindow::OnOutputTransformed(), screen rotation occurs, old[%d], new[%d\n", mScreenRotationAngle, newScreenRotationAngle);
- // Emit Resize signal
- Dali::GlWindow handle(this);
- mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
+ if(newScreenRotationAngle != mScreenRotationAngle)
+ {
+ UpdateScreenRotation(newScreenRotationAngle);
}
}
mWindowHeight = mPositionSize.height;
}
- mIsRotated = true;
- mIsWindowRotated = true;
DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), OnRotation(): resize signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight);
// Emit Resize signal
Dali::GlWindow handle(this);
mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
+
+ if(mGlWindowRenderThread)
+ {
+ mGlWindowRenderThread->RequestWindowRotate(mWindowRotationAngle);
+ }
}
void GlWindow::RecalculateTouchPosition(Integration::Point& point)
mGlWindowRenderThread->SetOnDemandRenderMode(onDemand);
mIsEGLInitialized = true;
+
+ // Check screen rotation
+ int newScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
+ DALI_LOG_RELEASE_INFO("GlWindow::InitializeGraphics(), GetScreenRotationAngle(): %d\n", mScreenRotationAngle);
+ if(newScreenRotationAngle != 0)
+ {
+ UpdateScreenRotation(newScreenRotationAngle);
+ }
}
}
{
}
+void GlWindow::UpdateScreenRotation(int newAngle)
+{
+ mScreenRotationAngle = newAngle;
+ mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
+
+ if(mTotalRotationAngle == 90 || mTotalRotationAngle == 270)
+ {
+ mWindowWidth = mPositionSize.height;
+ mWindowHeight = mPositionSize.width;
+ }
+ else
+ {
+ mWindowWidth = mPositionSize.width;
+ mWindowHeight = mPositionSize.height;
+ }
+
+ // Emit Resize signal
+ Dali::GlWindow handle(this);
+ mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
+
+ if(mGlWindowRenderThread)
+ {
+ DALI_LOG_RELEASE_INFO("GlWindow::UpdateScreenRotation(), RequestScreenRotatem(), mScreenRotationAngle: %d\n", mScreenRotationAngle);
+ mGlWindowRenderThread->RequestScreenRotate(mScreenRotationAngle);
+ }
+}
+
} // namespace Adaptor
} // namespace Internal
*/
void OnDamaged(const DamageArea& area);
+ /**
+ * @brief Updates screen rotation value and screen rotation works.
+ *
+ * @param[in] newAngle new screen rotation angle
+ */
+ void UpdateScreenRotation(int newAngle);
+
public: // Signals
/**
* @copydoc Dali::GlWindow::FocusChangeSignal()
bool mOpaqueState : 1;
bool mResizeEnabled : 1;
bool mVisible : 1;
- bool mIsRotated : 1;
bool mIsWindowRotated : 1;
bool mIsTouched : 1;
bool mIsEGLInitialized : 1;
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
+// EXTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/thread-settings.h>
+// INTERNAL INCLUDES
#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/system/common/time-service.h>
#include <dali/internal/window-system/common/gl-window-render-thread.h>
{
namespace
{
-const unsigned int NANOSECONDS_PER_SECOND(1e+9);
+constexpr unsigned int NANOSECONDS_PER_SECOND(1e+9);
// The following values will get calculated at compile time
-const float DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f);
-const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND);
+constexpr float DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f);
+constexpr uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND);
+constexpr uint64_t REFRESH_RATE(1u);
+constexpr int MINIMUM_DIMENSION_CHANGE(1);
} // namespace
GlWindowRenderThread::GlWindowRenderThread(PositionSize positionSize, ColorDepth colorDepth)
: mGraphics(nullptr),
mWindowBase(nullptr),
+ mWindowRotationTrigger(),
mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
mPositionSize(positionSize),
mColorDepth(colorDepth),
mIsEGLInitialize(false),
mGLESVersion(30), //Default GLES version 30
mMSAA(0),
+ mWindowRotationAngle(0),
+ mScreenRotationAngle(0),
mRenderThreadWaitCondition(),
mDestroyRenderThread(0),
mPauseRenderThread(0),
mRenderingMode(0),
- mRequestRenderOnce(0)
+ mRequestRenderOnce(0),
+ mSurfaceStatus(0),
+ mPostRendering(0),
+ mDefaultFrameDurationNanoseconds(REFRESH_RATE * DEFAULT_FRAME_DURATION_IN_NANOSECONDS)
{
- unsigned int refrashRate = 1u;
- mDefaultFrameDurationNanoseconds = uint64_t(refrashRate) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS;
}
GlWindowRenderThread::~GlWindowRenderThread()
mRenderThreadWaitCondition.Notify(lock);
}
+void GlWindowRenderThread::RequestWindowResize(int width, int height)
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ // Check resizing
+ if((fabs(width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
+ (fabs(height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE))
+ {
+ mSurfaceStatus |= static_cast<unsigned int>(SurfaceStatus::RESIZED); // Set bit for window resized
+ mPositionSize.width = width;
+ mPositionSize.height = height;
+
+ DALI_LOG_RELEASE_INFO("GlWindowRenderThread::RequestWindowResize(), width:%d, height:%d\n", width, height);
+ mRenderThreadWaitCondition.Notify(lock);
+ }
+}
+
+void GlWindowRenderThread::RequestWindowRotate(int windowAngle)
+{
+ if(!mWindowRotationTrigger)
+ {
+ mWindowRotationTrigger = std::unique_ptr<TriggerEventInterface>(TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &GlWindowRenderThread::WindowRotationCompleted),
+ TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+ }
+
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ if(mWindowRotationAngle != windowAngle)
+ {
+ mSurfaceStatus |= static_cast<unsigned int>(SurfaceStatus::WINDOW_ROTATED); // Set bit for window rotation
+ mWindowRotationAngle = windowAngle;
+ DALI_LOG_RELEASE_INFO("GlWindowRenderThread::RequestWindowRotate(): %d\n", windowAngle);
+ mRenderThreadWaitCondition.Notify(lock);
+ }
+}
+
+void GlWindowRenderThread::RequestScreenRotate(int screenAngle)
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ if(mScreenRotationAngle != screenAngle)
+ {
+ mSurfaceStatus |= static_cast<unsigned int>(SurfaceStatus::SCREEN_ROTATED); // Set bit for screen rotation
+ mScreenRotationAngle = screenAngle;
+ DALI_LOG_RELEASE_INFO("GlWindowRenderThread::RequestScreenRotate(): %d\n", screenAngle);
+ mRenderThreadWaitCondition.Notify(lock);
+ }
+}
+
+void GlWindowRenderThread::WindowRotationCompleted()
+{
+ mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
+
+ PostRenderFinish();
+}
+
+unsigned int GlWindowRenderThread::GetSurfaceStatus(int& windowRotationAngle, int& screenRotationAngle)
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+
+ // Get the surface status and reset that.
+ unsigned int status = mSurfaceStatus;
+ mSurfaceStatus = static_cast<unsigned int>(SurfaceStatus::NO_CHANGED);
+
+ windowRotationAngle = mWindowRotationAngle;
+ screenRotationAngle = mScreenRotationAngle;
+
+ return status;
+}
+
void GlWindowRenderThread::Run()
{
Dali::SetThreadName("GlWindowRenderThread");
mLogFactory.InstallLogFunction();
int renderFrameResult = 0;
- EglGraphics* eglGraphics = static_cast<EglGraphics*>(mGraphics);
+ unsigned int isSurfaceChanged = 0;
+ bool isWindowResized = false, isWindowRotated = false, isScreenRotated = false;
+ int windowRotationAngle = 0, screenRotationAngle = 0, totalAngle = 0;
+ EglGraphics* eglGraphics = static_cast<EglGraphics*>(mGraphics);
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
if(mGLRenderFrameCallback)
{
+ // PreRender
+ isSurfaceChanged = GetSurfaceStatus(windowRotationAngle, screenRotationAngle);
+ if(DALI_UNLIKELY(isSurfaceChanged))
+ {
+ isWindowResized = (isSurfaceChanged & static_cast<unsigned int>(SurfaceStatus::RESIZED)) ? true : false;
+ isWindowRotated = (isSurfaceChanged & static_cast<unsigned int>(SurfaceStatus::WINDOW_ROTATED)) ? true : false;
+ isScreenRotated = (isSurfaceChanged & static_cast<unsigned int>(SurfaceStatus::SCREEN_ROTATED)) ? true : false;
+ totalAngle = (windowRotationAngle + screenRotationAngle) % 360;
+
+ if(isWindowRotated || isScreenRotated)
+ {
+ mWindowBase->SetEglWindowBufferTransform(totalAngle);
+ if(isWindowRotated)
+ {
+ mWindowBase->SetEglWindowTransform(windowRotationAngle);
+ }
+ }
+
+ if(isWindowResized)
+ {
+ Dali::PositionSize positionSize;
+ positionSize.x = mPositionSize.x;
+ positionSize.y = mPositionSize.y;
+ if(totalAngle == 0 || totalAngle == 180)
+ {
+ positionSize.width = mPositionSize.width;
+ positionSize.height = mPositionSize.height;
+ }
+ else
+ {
+ positionSize.width = mPositionSize.height;
+ positionSize.height = mPositionSize.width;
+ }
+ mWindowBase->ResizeEglWindow(positionSize);
+ }
+ }
+
+ // Render
renderFrameResult = CallbackBase::ExecuteReturn<int>(*mGLRenderFrameCallback);
+ // PostRender
+ if(DALI_UNLIKELY(isWindowRotated))
+ {
+ PostRenderStart();
+
+ mWindowRotationTrigger->Trigger();
+
+ PostRenderWaitForFinished();
+ isWindowRotated = false;
+ }
+
+ // buffer commit
if(renderFrameResult)
{
eglImpl.SwapBuffers(mEGLSurface);
bool GlWindowRenderThread::RenderReady(uint64_t& timeToSleepUntil)
{
ConditionalWait::ScopedLock updateLock(mRenderThreadWaitCondition);
- while((!mDestroyRenderThread && mRenderingMode && !mRequestRenderOnce) || mPauseRenderThread)
+ while((!mDestroyRenderThread && mRenderingMode && !mRequestRenderOnce && !mSurfaceStatus) || mPauseRenderThread)
{
timeToSleepUntil = 0;
mRenderThreadWaitCondition.Wait(updateLock);
return !mDestroyRenderThread;
}
+void GlWindowRenderThread::PostRenderStart()
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ mPostRendering = false;
+}
+
+void GlWindowRenderThread::PostRenderFinish()
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ mPostRendering = true;
+ mRenderThreadWaitCondition.Notify(lock);
+}
+
+void GlWindowRenderThread::PostRenderWaitForFinished()
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ while(!mPostRendering && !mDestroyRenderThread)
+ {
+ mRenderThreadWaitCondition.Wait(lock);
+ }
+}
+
} // namespace Adaptor
} // namespace Internal
namespace Dali
{
class Adaptor;
+class TriggerEventInterface;
namespace Internal
{
{
public:
/**
+ * @brief Enumeration for GlWindow Surface status type
+ * It has the status as resized, window is rotated and screen is rotated.
+ *
+ */
+ enum class SurfaceStatus
+ {
+ NO_CHANGED = 0x00, ///< no changed,
+ RESIZED = 0x01, ///< When surface is resized,
+ WINDOW_ROTATED = 0x02, ///< When window is rotated,
+ SCREEN_ROTATED = 0x04 ///< When screen is rotated,
+ };
+
+ /**
* Constructor
*
* @param[in] positionSize The position and size of the physical window
*/
void RenderOnce();
+ /**
+ * Requests the window resize to GlWindow's render thread.
+ *
+ * @param[in] width new width.
+ * @param[in] height new height.
+ */
+ void RequestWindowResize(int width, int height);
+
+ /**
+ * Requests the window rotation to GlWindow's render thread.
+ *
+ * @param[in] windowAngle the window rotation's angle as 0, 90, 180 and 270.
+ */
+ void RequestWindowRotate(int windowAngle);
+
+ /**
+ * Requests the screen rotation to GlWindow's render thread.
+ *
+ * @param[in] screenAngle the screen rotation's angle as 0, 90, 180 and 270.
+ */
+ void RequestScreenRotate(int screenAngle);
+
protected:
/**
* The Render thread loop. This thread will be destroyed on exit from this function.
*/
bool RenderReady(uint64_t& timeToSleepUntil);
+ /**
+ * In the Tizen world, when GlWindow rotation is finished in client side,
+ * the completed message should be sent to display server.
+ * This function should be called in the event thread after buffer is committed.
+ */
+ void WindowRotationCompleted();
+
+ /**
+ * Gets window's current surface status
+ *
+ * @brief This function return window's current surface status.
+ * The status has the the information of window resized, window rotated and screen rotated.
+ * After called, the status value is reset
+ *
+ * @[output] windowRotationAngle return current window rotation angle.
+ * @[output] screenRotationAngle return current screen rotation angle.
+ * @return the window's current surface status.
+ */
+ unsigned int GetSurfaceStatus(int& windowRotationAngle, int& screenRotationAngle);
+
+ /**
+ * Starts post rendering process
+ *
+ * @brief Starts post rendering process for window rotation
+ * It is to pause the render thread until maint thread finishes the window rotation work.
+ */
+ void PostRenderStart();
+
+ /**
+ * Finishs post rendering process
+ *
+ * @brief Finishes post rendering process for window rotation
+ * It set the resume flag for resume the render thread.
+ */
+ void PostRenderFinish();
+
+ /**
+ * Pauses the render thread unitil post rendering process
+ *
+ * @brief Pauses the render thread until main thread works window rotation.
+ */
+ void PostRenderWaitForFinished();
+
private:
- GraphicsInterface* mGraphics; ///< Graphics interface
- WindowBase* mWindowBase;
+ GraphicsInterface* mGraphics; ///< Graphics interface
+ WindowBase* mWindowBase;
+ std::unique_ptr<TriggerEventInterface> mWindowRotationTrigger;
const Dali::LogFactoryInterface& mLogFactory;
bool mIsEGLInitialize : 1;
int mGLESVersion;
int mMSAA;
+ int mWindowRotationAngle; ///< The angle of window rotation angle
+ int mScreenRotationAngle; ///< The angle of screen rotation angle
// To manage the render/main thread
- ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
- volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried.
- volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause.
- volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad
- volatile unsigned int mRequestRenderOnce; ///< Request rendering once
+ ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
+ volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried.
+ volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause.
+ volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad
+ volatile unsigned int mRequestRenderOnce; ///< Request rendering once
+ volatile unsigned int mSurfaceStatus; ///< When surface is changed as resized or rotated, this flag is set. 0: No changed, 1:resized, 2:window rotation, 4:screen rotation
+ volatile unsigned int mPostRendering; ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
uint64_t mDefaultFrameDurationNanoseconds; ///< Default duration of a frame (used for sleeping if not enough time elapsed). Not protected by lock, but written to rarely so not worth adding a lock when reading.
{
const unsigned int ADAPTOR_MAJOR_VERSION = 2;
const unsigned int ADAPTOR_MINOR_VERSION = 0;
-const unsigned int ADAPTOR_MICRO_VERSION = 23;
+const unsigned int ADAPTOR_MICRO_VERSION = 25;
const char* const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-adaptor
Summary: The DALi Tizen Adaptor
-Version: 2.0.23
+Version: 2.0.25
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT