Previously we miss callback when ResourceReady called continusouly.
Let we use IdleCallbackManager system with return value, so we can
re-install Idle callback.
Change-Id: I56d73545ae7d8a122c8bead396affd4e962f7bb8
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
private:
Vector<CallbackBase*> mCallbacks;
+ Vector<CallbackBase*> mReturnCallbacks;
std::vector<Internal::Adaptor::SceneHolder*> mWindows;
Dali::Adaptor::AdaptorSignalType mResizedSignal;
Dali::Adaptor::AdaptorSignalType mLanguageChangedSignal;
bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
{
- mCallbacks.PushBack(callback);
+ if(hasReturnValue)
+ {
+ mReturnCallbacks.PushBack(callback);
+ }
+ else
+ {
+ mCallbacks.PushBack(callback);
+ }
return true;
}
void Adaptor::RemoveIdle(CallbackBase* callback)
{
mCallbacks.Erase(std::find_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }));
+ mReturnCallbacks.Erase(std::find_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }));
}
void Adaptor::RunIdles()
{
+ Dali::Vector<CallbackBase*> reusedCallbacks;
+ for(auto& callback : mReturnCallbacks)
+ {
+ bool retValue = CallbackBase::ExecuteReturn<bool>(*callback);
+ if(retValue)
+ {
+ reusedCallbacks.PushBack(callback);
+ }
+ }
for(auto& callback : mCallbacks)
{
CallbackBase::Execute(*callback);
}
mCallbacks.Clear();
+ mReturnCallbacks.Clear();
+ mReturnCallbacks.Swap(reusedCallbacks);
}
Dali::RenderSurfaceInterface& Adaptor::GetSurface()
gImageView2.Reset();
}
}
+constexpr int gResourceReadySignal10MaxCounter = 5;
+
+void OnResourceReadySignal10(Control control)
+{
+ gResourceReadySignalCounter++;
+
+ tet_printf("OnResourceReadySignal10 comes!\n");
+ if(gResourceReadySignalCounter < gResourceReadySignal10MaxCounter)
+ {
+ tet_printf("OnResourceReadySignal10 Set image\n");
+ gImageView1.SetProperty(Toolkit::ImageView::Property::IMAGE, gImage_34_RGBA);
+ tet_printf("OnResourceReadySignal10 Set image done\n");
+ }
+}
} // namespace
END_TEST;
}
+int UtcDaliImageViewSetImageOnResourceReadySignal10(void)
+{
+ tet_infoline("Test ResourceReady signal comes more than 2 times.");
+
+ ToolkitTestApplication application;
+
+ gResourceReadySignalCounter = 0;
+
+ // Clear image view for clear test
+
+ if(gImageView1)
+ {
+ gImageView1.Reset();
+ }
+
+ // Dummy view to cache image.
+ ImageView dummyView = ImageView::New(gImage_34_RGBA);
+ application.GetScene().Add(dummyView);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ try
+ {
+ gImageView1 = ImageView::New();
+ gImageView1.SetProperty(Toolkit::ImageView::Property::IMAGE, gImage_34_RGBA);
+ gImageView1.ResourceReadySignal().Connect(&OnResourceReadySignal10);
+ application.GetScene().Add(gImageView1); // It will call resourceReady signal 1 time.
+
+ tet_printf("ResourceReady called %d times\n", gResourceReadySignalCounter);
+
+ DALI_TEST_GREATER(gResourceReadySignal10MaxCounter, gResourceReadySignalCounter, TEST_LOCATION); // Check whether resource ready call too much.
+
+ for(int i = 0; i < gResourceReadySignal10MaxCounter; ++i)
+ {
+ tet_printf("RunIdles\n");
+ // Executes the idle callbacks.
+ application.RunIdles();
+ application.SendNotification();
+ application.Render();
+ tet_printf("RunIdles done\n");
+ }
+ tet_printf("ResourceReady called %d times\n", gResourceReadySignalCounter);
+
+ DALI_TEST_EQUALS(gResourceReadySignalCounter, gResourceReadySignal10MaxCounter, TEST_LOCATION);
+
+ DALI_TEST_CHECK(true);
+ }
+ catch(...)
+ {
+ // Exception should not happened
+ DALI_TEST_CHECK(false);
+ }
+
+ // Clear cache.
+ application.SendNotification();
+ application.Render();
+
+ gResourceReadySignalCounter = 0;
+
+ gResourceReadySignalCounter = 0;
+
+ // Clear image view for clear test
+
+ if(gImageView1)
+ {
+ gImageView1.Reset();
+ }
+
+ END_TEST;
+}
+
int UtcDaliImageViewUseSameUrlWithAnimatedImageVisual(void)
{
tet_infoline("Test multiple views with same image in animated image visual");
mIsKeyboardNavigationSupported(false),
mIsKeyboardFocusGroup(false),
mIsEmittingResourceReadySignal(false),
- mNeedToEmitResourceReady(false),
+ mIdleCallbackRegistered(false),
mDispatchKeyEvents(true)
{
Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
// Emit signal if all enabled visuals registered by the control are ready or there are no visuals.
if(IsResourceReady())
{
- // Reset the flag
- mNeedToEmitResourceReady = false;
EmitResourceReadySignal();
}
}
mIsEmittingResourceReadySignal = true;
// If the signal handler changes visual, it may become ready during this call & therefore this method will
- // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
+ // get called again recursively. If so, mIdleCallbackRegistered is set below, and we act on it after that secondary
// invocation has completed by notifying in an Idle callback to prevent further recursion.
Dali::Toolkit::Control handle(mControlImpl.GetOwner());
mResourceReadySignal.Emit(handle);
- if(mNeedToEmitResourceReady)
+ mIsEmittingResourceReadySignal = false;
+ }
+ else
+ {
+ if(!mIdleCallbackRegistered)
{
+ mIdleCallbackRegistered = true;
+
// Add idler to emit the signal again
if(!mIdleCallback)
{
// The callback manager takes the ownership of the callback object.
mIdleCallback = MakeCallback(this, &Control::Impl::OnIdleCallback);
- Adaptor::Get().AddIdle(mIdleCallback, false);
+ Adaptor::Get().AddIdle(mIdleCallback, true);
}
}
-
- mIsEmittingResourceReadySignal = false;
- }
- else
- {
- mNeedToEmitResourceReady = true;
}
}
-void Control::Impl::OnIdleCallback()
+bool Control::Impl::OnIdleCallback()
{
- if(mNeedToEmitResourceReady)
+ // Reset the flag
+ mIdleCallbackRegistered = false;
+
+ // A visual is ready so control may need relayouting if staged
+ if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
{
- // Reset the flag
- mNeedToEmitResourceReady = false;
+ mControlImpl.RelayoutRequest();
+ }
- // A visual is ready so control may need relayouting if staged
- if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
- {
- mControlImpl.RelayoutRequest();
- }
+ EmitResourceReadySignal();
- EmitResourceReadySignal();
+ if(!mIdleCallbackRegistered)
+ {
+ // Set the pointer to null as the callback manager deletes the callback after execute it.
+ mIdleCallback = nullptr;
}
- // Set the pointer to null as the callback manager deletes the callback after execute it.
- mIdleCallback = nullptr;
+ // Repeat idle if mIdleCallbackRegistered become true one more time.
+ return mIdleCallbackRegistered;
}
Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
/**
* @brief Callbacks called on idle.
+ *
+ * @return True if we need to call this idle callback one more time.
*/
- void OnIdleCallback();
+ bool OnIdleCallback();
/**
* @brief Checks highlighted object geometry if it is showing or not
bool mIsKeyboardNavigationSupported : 1; ///< Stores whether keyboard navigation is supported by the control.
bool mIsKeyboardFocusGroup : 1; ///< Stores whether the control is a focus group.
bool mIsEmittingResourceReadySignal : 1; ///< True during ResourceReady().
- bool mNeedToEmitResourceReady : 1; ///< True if need to emit the resource ready signal again.
+ bool mIdleCallbackRegistered : 1; ///< True if need to emit the resource ready signal again.
bool mDispatchKeyEvents : 1; ///< Whether the actor emits key event signals
RegisteredVisualContainer mRemoveVisuals; ///< List of visuals that are being replaced by another visual once ready