diff --git a/src/gui/core/callbackbase.cc b/src/gui/core/callbackbase.cc new file mode 100755 index 00000000..69ceace6 --- /dev/null +++ b/src/gui/core/callbackbase.cc @@ -0,0 +1,4 @@ +#include +namespace cdroid{ + std::atomic_int mCallbackID(0); +} diff --git a/src/gui/core/callbackbase.h b/src/gui/core/callbackbase.h new file mode 100755 index 00000000..27e58409 --- /dev/null +++ b/src/gui/core/callbackbase.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +namespace cdroid{ + +extern std::atomic_int mCallbackID; + +template +class CallbackBase{ +private: + using Functor=std::function; + Functor fun; + long mID; +public: + CallbackBase(){fun=nullptr_t();mID=mCallbackID++;} + CallbackBase(const Functor&a):CallbackBase(){ + fun=a; + } + CallbackBase&operator=(const Functor&a){ + fun=a; + return *this; + } + CallbackBase&operator=(const CallbackBase&b){ + mID=b.mID; + fun=b.fun; + return *this; + } + bool operator==(const CallbackBase&b)const{ + return mID==b.mID; + } + operator bool()const{ return fun!=nullptr; } + operator int() const{ return mID; } + bool operator==(nullptr_t)const{ + return fun==nullptr; + } + bool operator!=(nullptr_t)const{ + return fun!=nullptr; + } + R operator()(Args...args)const{ + return fun(std::forward(args)...); + } +}; +} + diff --git a/src/gui/core/choreographer.cc b/src/gui/core/choreographer.cc index 6a3db151..cc84d3a8 100755 --- a/src/gui/core/choreographer.cc +++ b/src/gui/core/choreographer.cc @@ -85,7 +85,7 @@ namespace cdroid{ CallbackRecord* predecessor = nullptr; for (CallbackRecord* callback = mHead; callback != nullptr;) { CallbackRecord* next = callback->next; - if ((/*action == nullptr ||*/ callback->action.ID == action.ID) + if ((/*action == nullptr ||*/ callback->action == action) && (token == 0 || callback->token == token)) { if (predecessor != nullptr) { predecessor->next = next; diff --git a/src/gui/core/context.h b/src/gui/core/context.h index 9df5b6c3..6a581458 100755 --- a/src/gui/core/context.h +++ b/src/gui/core/context.h @@ -5,43 +5,12 @@ #include #include #include - +#include using namespace Cairo; namespace cdroid{ -class Runnable{ -public: - int ID; - std::functionrun; - Runnable(){ - run=nullptr; - } - Runnable(const Runnable&b){ - run=b.run; - ID=b.ID; - } - Runnable(const std::function&f){ - run=f; - } - void operator=(const std::function&f){ - run=f; - } - void operator=(nullptr_t){ - run=nullptr; - } - bool operator==(nullptr_t)const{ - return run==nullptr; - } - bool operator!=(nullptr_t)const{ - return run!=nullptr; - } - explicit operator bool()const{ - return run!=nullptr; - } - void operator()(){ - run(); - } -}; + +typedef CallbackBase Runnable; class Drawable; class ColorStateList; class Context{ diff --git a/src/gui/core/uieventsource.cc b/src/gui/core/uieventsource.cc index 10ab48a4..ca0ecb7d 100755 --- a/src/gui/core/uieventsource.cc +++ b/src/gui/core/uieventsource.cc @@ -10,7 +10,6 @@ namespace cdroid{ UIEventSource::UIEventSource(View*v){ mAttachedView=v; - mID=0; } UIEventSource::~UIEventSource(){ @@ -28,18 +27,23 @@ int UIEventSource::handleEvents(){ } if(GraphDevice::getInstance().needCompose()) GraphDevice::getInstance().ComposeSurfaces(); + for(auto it=mRunnables.begin();it!=mRunnables.end();it++){ + LOGV_IF(it->removed,"remove %d",(int)it->run); + if(it->removed)it=mRunnables.erase(it); + } if(hasDelayedRunners()){ RUNNER runner=mRunnables.front(); - runner.run(); + runner.run();//maybe user will removed runnable itself in its runnable'proc,so we use removed flag to flag it + LOGV("remove %d",(int)runner.run); mRunnables.pop_front(); } return 0; } -void UIEventSource::post(Runnable& run,DWORD delayedtime){ +void UIEventSource::post(const Runnable& run,uint32_t delayedtime){ RUNNER runner; + runner.removed=false; runner.time=SystemClock::uptimeMillis()+delayedtime; - run.ID=mID++; runner.run=run; for(auto itr=mRunnables.begin();itr!=mRunnables.end();itr++){ if(runner.timetime){ @@ -58,9 +62,9 @@ bool UIEventSource::hasDelayedRunners()const{ } void UIEventSource::removeCallbacks(const Runnable& what){ - mRunnables.remove_if([&](const RUNNER& m)->bool{ - return (m.run.ID==what.ID); - }); + for(auto it=mRunnables.begin();it!=mRunnables.end();it++){ + if(it->run==what) it->removed=true; + } } }//end namespace diff --git a/src/gui/core/uieventsource.h b/src/gui/core/uieventsource.h index cb01f896..4d09ba5f 100755 --- a/src/gui/core/uieventsource.h +++ b/src/gui/core/uieventsource.h @@ -8,10 +8,10 @@ namespace cdroid{ class UIEventSource:public EventHandler{ private: - int mID; typedef struct{ - nsecs_t time; - Runnable run; + nsecs_t time; + bool removed; + Runnable run; }RUNNER; std::listmRunnables; View*mAttachedView; @@ -22,7 +22,7 @@ public: bool processEvents(); int checkEvents()override; int handleEvents()override; - void post(Runnable& run,DWORD delay=0); + void post(const Runnable& run,uint32_t delay=0); void removeCallbacks(const Runnable& what); }; diff --git a/src/gui/widget/adapterview.cc b/src/gui/widget/adapterview.cc index d387e975..65e087dd 100755 --- a/src/gui/widget/adapterview.cc +++ b/src/gui/widget/adapterview.cc @@ -387,7 +387,7 @@ void AdapterView::selectionChanged(){ // by posting. This ensures that the view tree is // in a consistent state and is able to accommodate // new layout or invalidate requests. - if (mSelectionNotifier == nullptr) { + if (mSelectionNotifier==nullptr) { mSelectionNotifier =[this](){ mPendingSelectionNotifier = nullptr; if (mDataChanged /*&& getViewRootImpl() && getViewRootImpl().isLayoutRequested()*/) { diff --git a/src/gui/widget/view.cc b/src/gui/widget/view.cc index f80ff5ee..67c6f560 100755 --- a/src/gui/widget/view.cc +++ b/src/gui/widget/view.cc @@ -3422,18 +3422,19 @@ bool View::onTouchEvent(MotionEvent& mt){ return false; } -void View::postOnAnimation(Runnable action){ +void View::postOnAnimation(const Runnable& action){ postDelayed(action,10); } -void View::postOnAnimationDelayed(Runnable action, long delayMillis){ + +void View::postOnAnimationDelayed(const Runnable& action, uint32_t delayMillis){ postDelayed(action,delayMillis); } -void View::post(Runnable& what){ +void View::post(const Runnable& what){ postDelayed(what,0); } -void View::postDelayed(Runnable& what,uint32_t delay){ +void View::postDelayed(const Runnable& what,uint32_t delay){ View*root=getRootView(); if(root&&(root!=this))root->postDelayed(what,delay); } diff --git a/src/gui/widget/view.h b/src/gui/widget/view.h index c11e8bd7..4d3f123e 100755 --- a/src/gui/widget/view.h +++ b/src/gui/widget/view.h @@ -354,8 +354,8 @@ protected: bool awakenScrollBars(); bool awakenScrollBars(int startDelay, bool invalidate); - void postOnAnimation(Runnable action); - void postOnAnimationDelayed(Runnable action, long delayMillis); + void postOnAnimation(const Runnable& action); + void postOnAnimationDelayed(const Runnable& action, uint32_t delayMillis); virtual void onSizeChanged(int w,int h,int oldw,int oldh); virtual void onScrollChanged(int l, int t, int oldl, int oldt); virtual void onLayout(bool ,int,int,int,int); @@ -679,10 +679,10 @@ public: virtual bool onGenericMotionEvent(MotionEvent& event); virtual void onHoverChanged(bool hovered); - void post(Runnable& what); + void post(const Runnable& what); void post(const std::function&what); void postDelayed(const std::function&what,uint32_t delay=0); - virtual void postDelayed(Runnable& what,uint32_t delay=0); + virtual void postDelayed(const Runnable& what,uint32_t delay=0); virtual void removeCallbacks(const Runnable& what); virtual int getBaseline(); diff --git a/src/gui/widget/window.cc b/src/gui/widget/window.cc index cfafc5b7..c356e918 100755 --- a/src/gui/widget/window.cc +++ b/src/gui/widget/window.cc @@ -283,7 +283,7 @@ bool Window::onKeyDown(int keyCode,KeyEvent& evt){ } -void Window::postDelayed(Runnable& what,uint32_t delay){ +void Window::postDelayed(const Runnable& what,uint32_t delay){ if(source)source->post(what,delay); } diff --git a/src/gui/widget/window.h b/src/gui/widget/window.h index b0d9c4f7..78cae7ce 100755 --- a/src/gui/widget/window.h +++ b/src/gui/widget/window.h @@ -71,7 +71,7 @@ public: sendMessage(this,msgid,wParam,lParam,delayedtime); } virtual void sendMessage(View*v,DWORD msgid,DWORD wParam,ULONG lParam,DWORD delayedtime=0)override;*/ - void postDelayed(Runnable& what,uint32_t delay)override; + void postDelayed(const Runnable& what,uint32_t delay)override; void removeCallbacks(const Runnable& what)override; void requestLayout()override; static void broadcast(DWORD msgid,DWORD wParam,ULONG lParam); diff --git a/tests/gui/CMakeLists.txt b/tests/gui/CMakeLists.txt old mode 100644 new mode 100755 index c516324c..878a1c3f --- a/tests/gui/CMakeLists.txt +++ b/tests/gui/CMakeLists.txt @@ -1,8 +1,9 @@ project(gui_test C CXX) - +set(CMAKE_CXX_STANDARD 11) aux_source_directory(./ SRCS_GUI_TESTS) include_directories( + ./ ${DEPS_DIR}/include ${DEPS_DIR}/include/gui ${DEPS_DIR}/include/porting diff --git a/tests/gui/callback.h b/tests/gui/callback.h new file mode 100755 index 00000000..1dfe82a2 --- /dev/null +++ b/tests/gui/callback.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include +#include +namespace test{ +static std::atomic_int ID(0); + +template +class CallbackBase{ +private: + using Functor=std::function; + Functor fun; + long mID; +public: + CallbackBase(){fun=nullptr_t();mID=ID++;} + CallbackBase(const Functor&a):CallbackBase(){ + fun=a; + } + CallbackBase&operator=(const Functor&a){ + fun=a; + return *this; + } + CallbackBase&operator=(const CallbackBase&b){ + mID=b.mID; + fun=b.fun; + return *this; + } + bool operator==(const CallbackBase&b){ + return mID==b.mID; + } + operator bool()const{ + return fun!=nullptr; + } + R operator()(Args...args)const{ + return fun(std::forward(args)...); + } +}; +} diff --git a/tests/gui/callback_tests.cc b/tests/gui/callback_tests.cc new file mode 100755 index 00000000..647ab62f --- /dev/null +++ b/tests/gui/callback_tests.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class CALLBACK:public testing::Test{ + + public : + virtual void SetUp(){ + } + virtual void TearDown(){ + } +}; + +TEST_F(CALLBACK,loop){ + test::CallbackBase c0([](){}); + test::CallbackBase c1([](int a){printf("a=%d\r\n",a);}); + test::CallbackBasecb2([](int a,int b){printf("a=%d,b=%d\r\n",a,b);}); + test::CallbackBasecbr2([](int a,int b){return a+b;}); + c1(123); + cb2(123,456); + printf("cbr2=%d\r\n",cbr2(234,345)); + cbr2=[](int a,int b){return a*b;}; + printf("cbr2=%d\r\n",cbr2(234,345)); +}