{\r
namespace Adaptor\r
{\r
+/**\r
+ * Structure contains the callback function and control options\r
+ */\r
+struct WindowsCallbackData\r
+{\r
+ /**\r
+ * Constructor\r
+ */\r
+ WindowsCallbackData(CallbackBase* callback, bool hasReturnValue)\r
+ : mCallback(callback),\r
+ mHasReturnValue(hasReturnValue)\r
+ {\r
+ }\r
+ /**\r
+ * Destructor\r
+ */\r
+ ~WindowsCallbackData()\r
+ {\r
+ delete mCallback;\r
+ }\r
+\r
+ CallbackBase* mCallback; ///< call back\r
+ bool mHasReturnValue; ///< true if the callback function has a return value.\r
+};\r
+\r
WinCallbackManager::WinCallbackManager()\r
: mRunning(false)\r
{\r
+ mSelfCallback = MakeCallback(this, &WinCallbackManager::ProcessIdleFromFramework);\r
+}\r
+\r
+WinCallbackManager::~WinCallbackManager()\r
+{\r
+ delete mSelfCallback;\r
}\r
\r
void WinCallbackManager::Start()\r
// make sure we're not called twice\r
DALI_ASSERT_DEBUG(mRunning == true);\r
\r
+ ClearIdleCallbacks();\r
+\r
mRunning = false;\r
}\r
\r
return false;\r
}\r
\r
- mCallbacks.insert(callback);\r
+ WindowsCallbackData* callbackData = new WindowsCallbackData(callback, hasReturnValue);\r
\r
- WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast<uint64_t>(callback), 0);\r
+ mCallbackContainer.push_back(callbackData);\r
+\r
+ if(!mSelfCallbackRegistered)\r
+ {\r
+ // Post only one times.\r
+ mSelfCallbackRegistered = true;\r
+ WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast<uint64_t>(mSelfCallback), 0);\r
+ }\r
\r
return true;\r
}\r
\r
void WinCallbackManager::RemoveIdleCallback(CallbackBase* callback)\r
{\r
- //Wait for deal\r
+ for(auto iter = mCallbackContainer.begin(), endIter = mCallbackContainer.end(); iter != endIter; ++iter)\r
+ {\r
+ auto* callbackData = *iter;\r
+\r
+ if(callbackData->mCallback == callback)\r
+ {\r
+ // delete our data\r
+ delete callbackData;\r
+\r
+ // Set stored value as nullptr. It will be removed from container after ProcessIdle()\r
+ (*iter) = nullptr;\r
+\r
+ return;\r
+ }\r
+ }\r
}\r
\r
bool WinCallbackManager::ProcessIdle()\r
{\r
- const bool idleProcessed = !mCallbacks.empty();\r
+ mSelfCallbackRegistered = false;\r
+\r
+ const bool idleProcessed = !mCallbackContainer.empty();\r
+\r
+ for(auto iter = mCallbackContainer.begin(); iter != mCallbackContainer.end();)\r
+ {\r
+ auto* callbackData = *iter;\r
+ bool removed = true;\r
+ if(callbackData)\r
+ {\r
+ if(callbackData->mHasReturnValue)\r
+ {\r
+ const bool retValue = Dali::CallbackBase::ExecuteReturn<bool>(*(callbackData->mCallback));\r
+\r
+ // Do not remove callback if return value is true.\r
+ removed = !retValue;\r
+ }\r
+ else\r
+ {\r
+ Dali::CallbackBase::Execute(*(callbackData->mCallback));\r
+ }\r
+ }\r
+\r
+ if(removed)\r
+ {\r
+ delete (*iter);\r
+ iter = mCallbackContainer.erase(iter);\r
+ }\r
+ else\r
+ {\r
+ ++iter;\r
+ }\r
+ }\r
\r
- // @todo : Need to consider callback with return & don't erase callback when it return true.\r
- for(CallbackBase* cb : mCallbacks)\r
+ // Re-register WIN_CALLBACK_EVENT when some idle callback remained.\r
+ if(!mCallbackContainer.empty())\r
{\r
- Dali::CallbackBase::Execute(*cb);\r
+ if(!mSelfCallbackRegistered)\r
+ {\r
+ // Post only one times.\r
+ mSelfCallbackRegistered = true;\r
+ WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast<uint64_t>(mSelfCallback), 0);\r
+ }\r
}\r
- mCallbacks.clear();\r
\r
return idleProcessed;\r
}\r
\r
void WinCallbackManager::ClearIdleCallbacks()\r
{\r
- mCallbacks.clear();\r
+ for(auto iter = mCallbackContainer.begin(), endIter = mCallbackContainer.end(); iter != endIter; ++iter)\r
+ {\r
+ auto* callbackData = *iter;\r
+ delete callbackData;\r
+ }\r
+ mCallbackContainer.clear();\r
}\r
\r
bool WinCallbackManager::AddIdleEntererCallback(CallbackBase* callback)\r
\r
void WinCallbackManager::RemoveIdleEntererCallback(CallbackBase* callback)\r
{\r
+ RemoveIdleCallback(callback);\r
+}\r
+\r
+void WinCallbackManager::ProcessIdleFromFramework()\r
+{\r
+ ProcessIdle();\r
}\r
\r
} // namespace Adaptor\r
*/
// EXTERNAL INCLUDES
-#include <set>
+#include <dali/public-api/common/list-wrapper.h>
// INTERNAL INCLUDES
#include <dali/internal/system/common/callback-manager.h>
{
namespace Adaptor
{
+struct WindowsCallbackData;
+
/**
- * @brief LibUV callback manager used to install call backs in the applications main loop.
+ * @brief Windows callback manager used to install call backs in the applications main loop.
* The manager keeps track of all callbacks, so that if Stop() is called it can remove them.
*/
class WinCallbackManager : public CallbackManager
/**
* @brief destructor
*/
- ~WinCallbackManager()
- {
- }
+ ~WinCallbackManager();
/**
* @copydoc CallbackManager::AddIdleCallback()
WinCallbackManager(const WinCallbackManager&) = delete;
WinCallbackManager& operator=(WinCallbackManager&) = delete;
+ /**
+ * @brief Callback function comes from framework.
+ * It will be self callback.
+ */
+ void ProcessIdleFromFramework();
+
private:
- std::set<CallbackBase*> mCallbacks;
- bool mRunning; ///< flag is set to true if when running
+ CallbackBase* mSelfCallback{nullptr};
+ bool mSelfCallbackRegistered{false}; ///< flag is set to true if we send processIdle callback register.
+
+ typedef std::list<WindowsCallbackData*> CallbackList;
+
+ CallbackList mCallbackContainer;
+ bool mRunning; ///< flag is set to true if when running
};
} // namespace Adaptor