2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "tizen-web-engine-lite.h"
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/common/stage.h>
24 #include <dali/public-api/events/key-event.h>
25 #include <dali/public-api/events/touch-data.h>
27 #include <libtuv/uv.h>
30 // The plugin factories
31 extern "C" DALI_EXPORT_API Dali::WebEnginePlugin* CreateWebEnginePlugin( void )
33 return new Dali::Plugin::TizenWebEngineLite;
36 extern "C" DALI_EXPORT_API void DestroyWebEnginePlugin( Dali::WebEnginePlugin* plugin )
44 #define TO_CONTAINER(ptr) (((TizenWebEngineLite*)ptr)->mWebContainer)
46 static bool gIsNeedsUpdate = false;
47 static bool gIsFirstTime = true;
48 static uv_async_t gLauncherHandle;
49 static pthread_mutex_t gMutex;
50 static bool gIsAliveMainLoop = false;
51 static int gDaliNumber = 0;
55 Locker(pthread_mutex_t& lock)
58 pthread_mutex_lock( &m_lock );
63 pthread_mutex_unlock( &m_lock );
66 pthread_mutex_t m_lock;
69 struct UVAsyncHandleData {
70 std::function<void(void*)> cb;
74 static bool IsAliveMainThread()
76 return gIsAliveMainLoop;
79 static void InitMainThread( void* (*f)(void*), pthread_t& t )
81 pthread_mutex_init(&gMutex, NULL);
83 pthread_mutex_lock(&gMutex);
85 pthread_attr_init(&attr);
86 pthread_create(&t, &attr, f, NULL);
87 pthread_mutex_lock(&gMutex);
88 pthread_mutex_unlock(&gMutex);
91 LWE::KeyValue KeyStringToKeyValue( const char* DALIKeyString, bool isShiftPressed )
93 LWE::KeyValue keyValue = LWE::KeyValue::UnidentifiedKey;
94 if( strcmp( "Left", DALIKeyString ) == 0 )
96 keyValue = LWE::KeyValue::ArrowLeftKey;
98 else if( strcmp( "Right", DALIKeyString ) == 0 )
100 keyValue = LWE::KeyValue::ArrowRightKey;
102 else if( strcmp( "Up", DALIKeyString ) == 0 )
104 keyValue = LWE::KeyValue::ArrowUpKey;
106 else if( strcmp( "Down", DALIKeyString ) == 0 )
108 keyValue = LWE::KeyValue::ArrowDownKey;
110 else if( strcmp( "space", DALIKeyString ) == 0 )
112 keyValue = LWE::KeyValue::SpaceKey;
114 else if( strcmp( "Return", DALIKeyString ) == 0 )
116 keyValue = LWE::KeyValue::EnterKey;
118 else if( strcmp( "BackSpace", DALIKeyString ) == 0 )
120 keyValue = LWE::KeyValue::BackspaceKey;
122 else if( strcmp( "Escape", DALIKeyString ) == 0 )
124 keyValue = LWE::KeyValue::EscapeKey;
126 else if( strcmp( "minus", DALIKeyString ) == 0 )
130 keyValue = LWE::KeyValue::MinusMarkKey;
134 keyValue = LWE::KeyValue::UnderScoreMarkKey;
137 else if( strcmp( "equal", DALIKeyString ) == 0 )
141 keyValue = LWE::KeyValue::PlusMarkKey;
145 keyValue = LWE::KeyValue::EqualitySignKey;
148 else if( strcmp( "bracketleft", DALIKeyString ) == 0 )
152 keyValue = LWE::KeyValue::LeftCurlyBracketMarkKey;
156 keyValue = LWE::KeyValue::LeftSquareBracketKey;
159 else if( strcmp( "bracketright", DALIKeyString ) == 0 )
163 keyValue = LWE::KeyValue::RightCurlyBracketMarkKey;
167 keyValue = LWE::KeyValue::RightSquareBracketKey;
170 else if( strcmp( "semicolon", DALIKeyString ) == 0 )
174 keyValue = LWE::KeyValue::ColonMarkKey;
178 keyValue = LWE::KeyValue::SemiColonMarkKey;
181 else if( strcmp( "apostrophe", DALIKeyString ) == 0 )
185 keyValue = LWE::KeyValue::DoubleQuoteMarkKey;
189 keyValue = LWE::KeyValue::SingleQuoteMarkKey;
192 else if( strcmp( "comma", DALIKeyString ) == 0 )
196 keyValue = LWE::KeyValue::LessThanMarkKey;
200 keyValue = LWE::KeyValue::CommaMarkKey;
203 else if( strcmp( "period", DALIKeyString ) == 0 )
207 keyValue = LWE::KeyValue::GreaterThanSignKey;
211 keyValue = LWE::KeyValue::PeriodKey;
214 else if( strcmp( "slash", DALIKeyString ) == 0 )
218 keyValue = LWE::KeyValue::QuestionMarkKey;
222 keyValue = LWE::KeyValue::SlashKey;
225 else if( strlen( DALIKeyString ) == 1 )
227 char ch = DALIKeyString[0];
228 if( ch >= '0' && ch <= '9' )
236 keyValue = LWE::KeyValue::ExclamationMarkKey;
241 keyValue = LWE::KeyValue::AtMarkKey;
246 keyValue = LWE::KeyValue::SharpMarkKey;
251 keyValue = LWE::KeyValue::DollarMarkKey;
256 keyValue = LWE::KeyValue::PercentMarkKey;
261 keyValue = LWE::KeyValue::CaretMarkKey;
266 keyValue = LWE::KeyValue::AmpersandMarkKey;
271 keyValue = LWE::KeyValue::AsteriskMarkKey;
276 keyValue = LWE::KeyValue::LeftParenthesisMarkKey;
281 keyValue = LWE::KeyValue::RightParenthesisMarkKey;
288 keyValue = ( LWE::KeyValue )( LWE::KeyValue::Digit0Key + ch - '0' );
291 else if( ch >= 'a' && ch <= 'z' )
293 int kv = LWE::KeyValue::LowerAKey + ch - 'a';
299 keyValue = (LWE::KeyValue)kv;
315 const int TIMER_INTERVAL( 20 );
317 } // unnamed namespace
319 TizenWebEngineLite::TizenWebEngineLite()
321 mIsMouseLbuttonDown( false ),
327 mOutputBuffer ( NULL ),
329 mCanGoForward( false ),
331 mWebContainer( NULL ),
332 #ifdef STARFISH_DALI_TBMSURFACE
334 mNativeImageSourcePtr( NULL )
341 TizenWebEngineLite::~TizenWebEngineLite()
345 bool TizenWebEngineLite::UpdateBuffer()
347 if( mIsRunning == false )
355 #ifdef STARFISH_DALI_TBMSURFACE
356 Dali::Stage::GetCurrent().KeepRendering( 0.0f );
362 mBufferImage.Update();
364 gIsNeedsUpdate = false;
370 void TizenWebEngineLite::StartMainThreadIfNeeds()
372 if ( !IsAliveMainThread() )
374 InitMainThread( StartMainThread, mThreadHandle );
378 void TizenWebEngineLite::CreateInstance()
381 auto cb = []( void* data )
383 TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
384 if ( !LWE::LWE::IsInitialized() )
386 LWE::LWE::Initialize("/tmp/StarFish_localStorage.txt",
387 "/tmp/StarFish_Cookies.txt", "/tmp/StarFish-cache");
389 engine->mWebContainer = LWE::WebContainer::Create(
390 engine->mOutputBuffer, engine->mOutputWidth, engine->mOutputHeight,
391 engine->mOutputStride, 1.0, "SamsungOne", "ko-KR", "Asia/Seoul" );
392 TO_CONTAINER( data )->RegisterOnRenderedHandler(
393 [ engine ]( LWE::WebContainer* container, const LWE::WebContainer::RenderResult& renderResult )
395 engine->onRenderedHandler( container, renderResult );
397 TO_CONTAINER( data )->RegisterOnReceivedErrorHandler(
398 [ engine ]( LWE::WebContainer* container, LWE::ResourceError error )
400 engine->mCanGoBack = container->CanGoBack();
401 engine->mCanGoForward = container->CanGoForward();
402 engine->onReceivedError( container, error );
404 TO_CONTAINER( data )->RegisterOnPageStartedHandler(
405 [ engine ]( LWE::WebContainer* container, const std::string& url )
408 engine->mCanGoBack = container->CanGoBack();
409 engine->mCanGoForward = container->CanGoForward();
410 engine->onPageStartedHandler( container, url );
412 TO_CONTAINER( data )->RegisterOnPageLoadedHandler(
413 [ engine ]( LWE::WebContainer* container, const std::string& url )
416 engine->mCanGoBack = container->CanGoBack();
417 engine->mCanGoForward = container->CanGoForward();
418 engine->onPageFinishedHandler( container, url );
420 TO_CONTAINER( data )->RegisterOnLoadResourceHandler(
421 [ engine ]( LWE::WebContainer* container, const std::string& url )
424 engine->mCanGoBack = container->CanGoBack();
425 engine->mCanGoForward = container->CanGoForward();
426 engine->onLoadResourceHandler( container, url );
429 SendAsyncHandle( cb );
432 void TizenWebEngineLite::Create( int width, int height, const std::string& locale, const std::string& timezoneId )
434 mTimer = Dali::Timer::New( TIMER_INTERVAL );
435 mTimer.TickSignal().Connect( this, &TizenWebEngineLite::UpdateBuffer );
438 StartMainThreadIfNeeds();
441 mOutputWidth = width;
442 mOutputHeight = height;
443 mOutputStride = width * sizeof( uint32_t );
444 mOutputBuffer = ( uint8_t* )malloc( width * height * sizeof( uint32_t ) );
446 if( gIsFirstTime == true )
448 gIsFirstTime = false;
450 onRenderedHandler = [this]( LWE::WebContainer* c, const LWE::WebContainer::RenderResult& renderResult )
453 size_t w = mOutputWidth;
454 size_t h = mOutputHeight;
455 if( renderResult.updatedWidth != w || renderResult.updatedHeight != h )
463 #ifdef STARFISH_DALI_TBMSURFACE
464 tbm_surface_info_s tbmSurfaceInfo;
465 if( tbm_surface_map( mTbmSurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &tbmSurfaceInfo ) != TBM_SURFACE_ERROR_NONE )
467 DALI_LOG_ERROR( "Fail to map tbm_surface\n" );
470 DALI_ASSERT_ALWAYS( tbmSurfaceInfo.format == TBM_FORMAT_ABGR8888 && "Unsupported TizenWebEngineLite tbm format" );
472 dstBuffer = tbmSurfaceInfo.planes[0].ptr;
473 dstStride = tbmSurfaceInfo.planes[0].stride;
476 dstBuffer = mBufferImage.GetBuffer();
477 dstStride = mBufferImage.GetBufferStride();
480 uint32_t srcStride = renderResult.updatedWidth * sizeof(uint32_t);
481 uint8_t* srcBuffer = static_cast< uint8_t* >( renderResult.updatedBufferAddress );
483 if (dstStride == srcStride)
485 memcpy( dstBuffer, srcBuffer, tbmSurfaceInfo.planes[0].size );
489 for ( auto y = renderResult.updatedY; y < ( renderResult.updatedHeight + renderResult.updatedY ); y++ )
491 auto start = renderResult.updatedX;
492 memcpy( dstBuffer + ( y * dstStride ) + ( start * 4 ), srcBuffer + ( y * srcStride ) + ( start * 4 ), srcStride );
496 #ifdef STARFISH_DALI_TBMSURFACE
497 if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
499 DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
502 gIsNeedsUpdate = true;
505 onReceivedError = []( LWE::WebContainer* container, LWE::ResourceError error ) {
507 onPageStartedHandler = []( LWE::WebContainer* container, const std::string& url ) {
509 onPageFinishedHandler = []( LWE::WebContainer* container, const std::string& url ) {
511 onLoadResourceHandler = []( LWE::WebContainer* container, const std::string& url ) {
515 #ifdef STARFISH_DALI_TBMSURFACE
516 mTbmSurface = tbm_surface_create( width, height, TBM_FORMAT_ABGR8888 );
517 mNativeImageSourcePtr = Dali::NativeImageSource::New( mTbmSurface );
519 mBufferImage = Dali::BufferImage::New( width, height, Dali::Pixel::RGBA8888 );
533 void TizenWebEngineLite::Destroy()
540 if( mIsRunning == true )
544 #ifdef STARFISH_DALI_TBMSURFACE
545 if( mTbmSurface != NULL && tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
547 DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
555 pthread_join( mThreadHandle, ( void** )&status );
557 mWebContainer = NULL;
561 void TizenWebEngineLite::DestroyInstance()
563 DALI_ASSERT_ALWAYS( mWebContainer );
564 auto cb = []( void* data )
566 TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
568 TO_CONTAINER( data )->Destroy();
570 while ( !engine->mAsyncHandlePool.empty() )
572 UVAsyncHandleData* handleData = NULL;
575 handleData = ( UVAsyncHandleData* )*engine->mAsyncHandlePool.begin();
576 engine->mAsyncHandlePool.erase( engine->mAsyncHandlePool.begin() );
580 handleData->cb( handleData->data );
586 SendAsyncHandle( cb );
589 Dali::NativeImageInterfacePtr TizenWebEngineLite::GetNativeImageSource()
591 return mNativeImageSourcePtr;
594 void TizenWebEngineLite::LoadUrl( const std::string& url )
596 DALI_ASSERT_ALWAYS( mWebContainer );
597 auto cb = [url]( void* data )
599 TO_CONTAINER( data )->LoadURL( url );
601 SendAsyncHandle( cb );
604 const std::string& TizenWebEngineLite::GetUrl()
606 DALI_ASSERT_ALWAYS( mWebContainer );
610 void TizenWebEngineLite::LoadHTMLString( const std::string& str )
612 DALI_ASSERT_ALWAYS( mWebContainer );
613 auto cb = [str]( void* data )
615 TO_CONTAINER( data )->LoadData( str );
617 SendAsyncHandle( cb );
620 void TizenWebEngineLite::Reload()
622 DALI_ASSERT_ALWAYS( mWebContainer );
623 auto cb = []( void* data )
625 TO_CONTAINER( data )->Reload();
627 SendAsyncHandle( cb );
630 void TizenWebEngineLite::StopLoading()
632 DALI_ASSERT_ALWAYS( mWebContainer );
633 auto cb = []( void* data )
635 TO_CONTAINER( data )->StopLoading();
637 SendAsyncHandle( cb );
640 void TizenWebEngineLite::GoBack()
642 DALI_ASSERT_ALWAYS( mWebContainer );
643 auto cb = []( void* data )
645 TO_CONTAINER( data )->GoBack();
647 SendAsyncHandle( cb );
650 void TizenWebEngineLite::GoForward()
652 DALI_ASSERT_ALWAYS( mWebContainer );
653 auto cb = []( void* data )
655 TO_CONTAINER( data )->GoForward();
657 SendAsyncHandle( cb );
660 bool TizenWebEngineLite::CanGoBack()
662 DALI_ASSERT_ALWAYS( mWebContainer );
666 bool TizenWebEngineLite::CanGoForward()
668 DALI_ASSERT_ALWAYS( mWebContainer );
669 return mCanGoForward;
672 void TizenWebEngineLite::EvaluateJavaScript( const std::string& script )
674 DALI_ASSERT_ALWAYS( mWebContainer );
675 auto cb = [script]( void* data ) {
676 TO_CONTAINER( data )->EvaluateJavaScript( script );
678 SendAsyncHandle( cb );
681 void TizenWebEngineLite::AddJavaScriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName, std::function< std::string(const std::string&) > callback )
683 DALI_ASSERT_ALWAYS( mWebContainer );
684 auto cb = [exposedObjectName, jsFunctionName, callback]( void* data )
686 TO_CONTAINER( data )->AddJavaScriptInterface( exposedObjectName, jsFunctionName, callback );
688 SendAsyncHandle( cb );
691 void TizenWebEngineLite::RemoveJavascriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName )
693 DALI_ASSERT_ALWAYS( mWebContainer );
694 auto cb = [exposedObjectName, jsFunctionName]( void* data )
696 TO_CONTAINER( data )->RemoveJavascriptInterface( exposedObjectName, jsFunctionName );
698 SendAsyncHandle( cb );
701 void TizenWebEngineLite::ClearHistory()
703 DALI_ASSERT_ALWAYS( mWebContainer );
704 auto cb = []( void* data )
706 TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
707 TO_CONTAINER( data )->ClearHistory();
708 engine->mCanGoBack = TO_CONTAINER( data )->CanGoBack();
710 SendAsyncHandle( cb );
713 void TizenWebEngineLite::ClearCache()
715 DALI_ASSERT_ALWAYS( mWebContainer );
716 auto cb = []( void* data )
718 TO_CONTAINER( data )->ClearCache();
720 SendAsyncHandle( cb );
723 void TizenWebEngineLite::SetSize( int width, int height )
725 DALI_ASSERT_ALWAYS( mWebContainer );
727 if( mOutputWidth != ( size_t )width || mOutputHeight != ( size_t )height )
730 mOutputWidth = width;
731 mOutputHeight = height;
732 mOutputStride = width * sizeof(uint32_t);
734 #ifdef STARFISH_DALI_TBMSURFACE
735 tbm_surface_h prevTbmSurface = mTbmSurface;
736 mTbmSurface = tbm_surface_create( width, height, TBM_FORMAT_ABGR8888 );
737 Dali::Any source( mTbmSurface );
738 mNativeImageSourcePtr->SetSource( source );
739 if( prevTbmSurface != NULL && tbm_surface_destroy( prevTbmSurface ) != TBM_SURFACE_ERROR_NONE )
741 DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
745 auto cb = []( void* data )
747 TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
750 if (engine->mOutputBuffer) {
751 free(engine->mOutputBuffer);
752 engine->mOutputBuffer = NULL;
755 engine->mOutputBuffer = ( uint8_t* )malloc( engine->mOutputWidth * engine->mOutputHeight * sizeof( uint32_t ) );
756 engine->mOutputStride = engine->mOutputWidth * sizeof( uint32_t );
757 engine->mWebContainer->UpdateBuffer( engine->mOutputBuffer, engine->mOutputWidth,
758 engine->mOutputHeight, engine->mOutputStride );
760 SendAsyncHandle( cb );
764 void TizenWebEngineLite::DispatchMouseDownEvent( float x, float y )
766 DALI_ASSERT_ALWAYS( mWebContainer );
772 auto cb = [x, y]( void* data )
774 TO_CONTAINER( data )->DispatchMouseDownEvent( LWE::MouseButtonValue::LeftButton, LWE::MouseButtonsValue::LeftButtonDown, x, y );
776 SendAsyncHandle( cb );
779 void TizenWebEngineLite::DispatchMouseUpEvent( float x, float y )
781 DALI_ASSERT_ALWAYS( mWebContainer );
787 auto cb = [x, y]( void* data )
789 TO_CONTAINER( data )->DispatchMouseUpEvent( LWE::MouseButtonValue::NoButton, LWE::MouseButtonsValue::NoButtonDown, x, y );
791 SendAsyncHandle( cb );
794 void TizenWebEngineLite::DispatchMouseMoveEvent( float x, float y, bool isLButtonPressed, bool isRButtonPressed )
796 DALI_ASSERT_ALWAYS( mWebContainer );
802 auto cb = [x, y, isLButtonPressed]( void* data )
804 TO_CONTAINER( data )->DispatchMouseMoveEvent(
805 isLButtonPressed ? LWE::MouseButtonValue::LeftButton
806 : LWE::MouseButtonValue::NoButton,
807 isLButtonPressed ? LWE::MouseButtonsValue::LeftButtonDown
808 : LWE::MouseButtonsValue::NoButtonDown, x, y );
810 SendAsyncHandle( cb );
813 bool TizenWebEngineLite::SendTouchEvent( const TouchData& touch )
815 size_t pointCount = touch.GetPointCount();
816 if( pointCount == 1 )
818 // Single touch event
819 Dali::PointState::Type pointState = touch.GetState( 0 );
820 const Dali::Vector2& screen = touch.GetLocalPosition( 0 );
822 if( pointState == Dali::PointState::DOWN )
824 DispatchMouseDownEvent( screen.x, screen.y );
825 mIsMouseLbuttonDown = true;
827 else if( pointState == Dali::PointState::UP )
829 DispatchMouseUpEvent( screen.x, screen.y );
830 mIsMouseLbuttonDown = false;
834 DispatchMouseMoveEvent( screen.x, screen.y, mIsMouseLbuttonDown, false );
841 void TizenWebEngineLite::DispatchKeyDownEvent( LWE::KeyValue keyCode )
843 DALI_ASSERT_ALWAYS( mWebContainer );
849 auto cb = [keyCode]( void* data )
851 TO_CONTAINER( data )->DispatchKeyDownEvent( keyCode );
853 SendAsyncHandle( cb );
856 void TizenWebEngineLite::DispatchKeyPressEvent( LWE::KeyValue keyCode )
858 DALI_ASSERT_ALWAYS( mWebContainer );
864 auto cb = [keyCode]( void* data )
866 TO_CONTAINER( data )->DispatchKeyPressEvent( keyCode );
868 SendAsyncHandle( cb );
871 void TizenWebEngineLite::DispatchKeyUpEvent( LWE::KeyValue keyCode )
873 DALI_ASSERT_ALWAYS( mWebContainer );
879 auto cb = [keyCode]( void* data )
881 TO_CONTAINER( data )->DispatchKeyUpEvent(keyCode);
883 SendAsyncHandle( cb );
886 bool TizenWebEngineLite::SendKeyEvent( const Dali::KeyEvent& event )
888 LWE::KeyValue keyValue = LWE::KeyValue::UnidentifiedKey;
889 if( 32 < event.keyPressed.c_str()[0] && 127 > event.keyPressed.c_str()[0] )
891 keyValue = static_cast<LWE::KeyValue>(event.keyPressed.c_str()[0]);
895 keyValue = KeyStringToKeyValue( event.keyPressedName.c_str(), event.keyModifier & 1 );
897 if( event.state == Dali::KeyEvent::Down )
899 DispatchKeyDownEvent( keyValue );
900 DispatchKeyPressEvent( keyValue );
902 else if( event.state == Dali::KeyEvent::Up )
904 DispatchKeyUpEvent( keyValue );
910 void TizenWebEngineLite::CallEmptyAsyncHandle()
912 DALI_ASSERT_ALWAYS( mWebContainer );
913 auto cb = []( void* data ) {
915 SendAsyncHandle( cb );
918 void TizenWebEngineLite::StopLoop()
921 CallEmptyAsyncHandle();
924 void TizenWebEngineLite::SendAsyncHandle(std::function<void(void*)> cb)
926 UVAsyncHandleData* handle = new UVAsyncHandleData();
932 mAsyncHandlePool.push_back( ( size_t )handle );
935 gLauncherHandle.data = this;
936 uv_async_send(&gLauncherHandle);
939 void* TizenWebEngineLite::StartMainThread( void* data )
941 uv_async_init( uv_default_loop(), &gLauncherHandle, []( uv_async_t* handle )
943 Dali::Plugin::TizenWebEngineLite* engine = static_cast< Dali::Plugin::TizenWebEngineLite* >(handle->data);
944 while ( !engine->mAsyncHandlePool.empty() )
946 UVAsyncHandleData* handleData = NULL;
949 handleData = ( UVAsyncHandleData* )*engine->mAsyncHandlePool.begin();
950 engine->mAsyncHandlePool.erase( engine->mAsyncHandlePool.begin() );
955 handleData->cb( handleData->data );
961 gIsAliveMainLoop = true;
962 pthread_mutex_unlock( &gMutex );
965 uv_run( uv_default_loop(), UV_RUN_ONCE );
966 if ( gDaliNumber < 0 )
974 } // namespace Plugin