Revert "[Tizen] Update web-engine-plugin to sync with LWE library and dali-adaptor"
[platform/core/uifw/dali-extension.git] / dali-extension / web-engine-lite / tizen-web-engine-lite.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "tizen-web-engine-lite.h"
20
21 // EXTERNAL INCLUDES
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>
26
27 #include <libtuv/uv.h>
28 #include <unistd.h>
29
30 // The plugin factories
31 extern "C" DALI_EXPORT_API Dali::WebEnginePlugin* CreateWebEnginePlugin( void )
32 {
33   return new Dali::Plugin::TizenWebEngineLite;
34 }
35
36 extern "C" DALI_EXPORT_API void DestroyWebEnginePlugin( Dali::WebEnginePlugin* plugin )
37 {
38   if( plugin != NULL )
39   {
40     delete plugin;
41   }
42 }
43
44 #define TO_CONTAINER(ptr) (((TizenWebEngineLite*)ptr)->mWebContainer)
45
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;
52
53 class Locker {
54 public:
55   Locker(pthread_mutex_t& lock)
56     : m_lock( lock )
57   {
58     pthread_mutex_lock( &m_lock );
59   }
60
61   ~Locker()
62   {
63     pthread_mutex_unlock( &m_lock );
64   }
65 protected:
66   pthread_mutex_t m_lock;
67 };
68
69 struct UVAsyncHandleData {
70   std::function<void(void*)> cb;
71   void* data;
72 };
73
74 static bool IsAliveMainThread()
75 {
76   return gIsAliveMainLoop;
77 }
78
79 static void InitMainThread( void* (*f)(void*), pthread_t& t )
80 {
81   pthread_mutex_init(&gMutex, NULL);
82
83   pthread_mutex_lock(&gMutex);
84   pthread_attr_t attr;
85   pthread_attr_init(&attr);
86   pthread_create(&t, &attr, f, NULL);
87   pthread_mutex_lock(&gMutex);
88   pthread_mutex_unlock(&gMutex);
89 }
90
91 LWE::KeyValue KeyStringToKeyValue( const char* DALIKeyString, bool isShiftPressed )
92 {
93   LWE::KeyValue keyValue = LWE::KeyValue::UnidentifiedKey;
94   if( strcmp( "Left", DALIKeyString ) == 0 )
95   {
96     keyValue = LWE::KeyValue::ArrowLeftKey;
97   }
98   else if( strcmp( "Right", DALIKeyString ) == 0 )
99   {
100     keyValue = LWE::KeyValue::ArrowRightKey;
101   }
102   else if( strcmp( "Up", DALIKeyString ) == 0 )
103   {
104     keyValue = LWE::KeyValue::ArrowUpKey;
105   }
106   else if( strcmp( "Down", DALIKeyString ) == 0 )
107   {
108     keyValue = LWE::KeyValue::ArrowDownKey;
109   }
110   else if( strcmp( "space", DALIKeyString ) == 0 )
111   {
112     keyValue = LWE::KeyValue::SpaceKey;
113   }
114   else if( strcmp( "Return", DALIKeyString ) == 0 )
115   {
116     keyValue = LWE::KeyValue::EnterKey;
117   }
118   else if( strcmp( "BackSpace", DALIKeyString ) == 0 )
119   {
120     keyValue = LWE::KeyValue::BackspaceKey;
121   }
122   else if( strcmp( "Escape", DALIKeyString ) == 0 )
123   {
124     keyValue = LWE::KeyValue::EscapeKey;
125   }
126   else if( strcmp( "minus", DALIKeyString ) == 0 )
127   {
128     if( isShiftPressed )
129     {
130       keyValue = LWE::KeyValue::MinusMarkKey;
131     }
132     else
133     {
134       keyValue = LWE::KeyValue::UnderScoreMarkKey;
135     }
136   }
137   else if( strcmp( "equal", DALIKeyString ) == 0 )
138   {
139     if( isShiftPressed )
140     {
141       keyValue = LWE::KeyValue::PlusMarkKey;
142     }
143     else
144     {
145       keyValue = LWE::KeyValue::EqualitySignKey;
146     }
147   }
148   else if( strcmp( "bracketleft", DALIKeyString ) == 0 )
149   {
150     if( isShiftPressed )
151     {
152       keyValue = LWE::KeyValue::LeftCurlyBracketMarkKey;
153     }
154     else
155     {
156       keyValue = LWE::KeyValue::LeftSquareBracketKey;
157     }
158   }
159   else if( strcmp( "bracketright", DALIKeyString ) == 0 )
160   {
161     if( isShiftPressed )
162     {
163       keyValue = LWE::KeyValue::RightCurlyBracketMarkKey;
164     }
165     else
166     {
167       keyValue = LWE::KeyValue::RightSquareBracketKey;
168     }
169   }
170   else if( strcmp( "semicolon", DALIKeyString ) == 0 )
171   {
172     if( isShiftPressed )
173     {
174       keyValue = LWE::KeyValue::ColonMarkKey;
175     }
176     else
177     {
178       keyValue = LWE::KeyValue::SemiColonMarkKey;
179     }
180   }
181   else if( strcmp( "apostrophe", DALIKeyString ) == 0 )
182   {
183     if( isShiftPressed )
184     {
185       keyValue = LWE::KeyValue::DoubleQuoteMarkKey;
186     }
187     else
188     {
189       keyValue = LWE::KeyValue::SingleQuoteMarkKey;
190     }
191   }
192   else if( strcmp( "comma", DALIKeyString ) == 0 )
193   {
194     if( isShiftPressed )
195     {
196       keyValue = LWE::KeyValue::LessThanMarkKey;
197     }
198     else
199     {
200       keyValue = LWE::KeyValue::CommaMarkKey;
201     }
202   }
203   else if( strcmp( "period", DALIKeyString ) == 0 )
204   {
205     if( isShiftPressed )
206     {
207       keyValue = LWE::KeyValue::GreaterThanSignKey;
208     }
209     else
210     {
211       keyValue = LWE::KeyValue::PeriodKey;
212     }
213   }
214   else if( strcmp( "slash", DALIKeyString ) == 0 )
215   {
216     if( isShiftPressed )
217     {
218       keyValue = LWE::KeyValue::QuestionMarkKey;
219     }
220     else
221     {
222       keyValue = LWE::KeyValue::SlashKey;
223     }
224   }
225   else if( strlen( DALIKeyString ) == 1 )
226   {
227     char ch = DALIKeyString[0];
228     if( ch >= '0' && ch <= '9' )
229     {
230       if( isShiftPressed )
231       {
232         switch( ch )
233         {
234           case '1':
235           {
236             keyValue = LWE::KeyValue::ExclamationMarkKey;
237             break;
238           }
239           case '2':
240           {
241             keyValue = LWE::KeyValue::AtMarkKey;
242             break;
243           }
244           case '3':
245           {
246             keyValue = LWE::KeyValue::SharpMarkKey;
247             break;
248           }
249           case '4':
250           {
251             keyValue = LWE::KeyValue::DollarMarkKey;
252             break;
253           }
254           case '5':
255           {
256             keyValue = LWE::KeyValue::PercentMarkKey;
257             break;
258           }
259           case '6':
260           {
261             keyValue = LWE::KeyValue::CaretMarkKey;
262             break;
263           }
264           case '7':
265           {
266             keyValue = LWE::KeyValue::AmpersandMarkKey;
267             break;
268           }
269           case '8':
270           {
271             keyValue = LWE::KeyValue::AsteriskMarkKey;
272             break;
273           }
274           case '9':
275           {
276             keyValue = LWE::KeyValue::LeftParenthesisMarkKey;
277             break;
278           }
279           case '0':
280           {
281             keyValue = LWE::KeyValue::RightParenthesisMarkKey;
282             break;
283           }
284         }
285       }
286       else
287       {
288         keyValue = ( LWE::KeyValue )( LWE::KeyValue::Digit0Key + ch - '0' );
289       }
290     }
291     else if( ch >= 'a' && ch <= 'z' )
292     {
293       int kv = LWE::KeyValue::LowerAKey + ch - 'a';
294       if( isShiftPressed )
295       {
296         kv -= ( 'z' - 'a' );
297         kv -= 7;
298       }
299       keyValue = (LWE::KeyValue)kv;
300     }
301   }
302   return keyValue;
303 }
304
305
306 namespace Dali
307 {
308
309 namespace Plugin
310 {
311
312 namespace
313 {
314
315 const int TIMER_INTERVAL( 20 );
316
317 } // unnamed namespace
318
319 TizenWebEngineLite::TizenWebEngineLite()
320 : mThreadHandle(),
321   mIsMouseLbuttonDown( false ),
322   mTimer(),
323   mUrl( "" ),
324   mOutputWidth( 0 ),
325   mOutputHeight( 0 ),
326   mOutputStride( 0 ),
327   mOutputBuffer ( NULL ),
328   mCanGoBack( false ),
329   mCanGoForward( false ),
330   mIsRunning( false ),
331   mWebContainer( NULL ),
332 #ifdef STARFISH_DALI_TBMSURFACE
333   mTbmSurface( NULL ),
334   mNativeImageSourcePtr( NULL )
335 #else
336   mBufferImage( NULL )
337 #endif
338 {
339 }
340
341 TizenWebEngineLite::~TizenWebEngineLite()
342 {
343 }
344
345 bool TizenWebEngineLite::UpdateBuffer()
346 {
347   if( mIsRunning == false )
348   {
349     return true;
350   }
351
352   if( gIsNeedsUpdate )
353   {
354     Locker l( gMutex );
355 #ifdef STARFISH_DALI_TBMSURFACE
356     Dali::Stage::GetCurrent().KeepRendering( 0.0f );
357 #else
358     if( !mBufferImage )
359     {
360       return false;
361     }
362     mBufferImage.Update();
363 #endif
364     gIsNeedsUpdate = false;
365   }
366
367   return true;
368 }
369
370 void TizenWebEngineLite::StartMainThreadIfNeeds()
371 {
372   if ( !IsAliveMainThread() )
373   {
374     InitMainThread( StartMainThread, mThreadHandle );
375   }
376 }
377
378 void TizenWebEngineLite::CreateInstance()
379 {
380   gDaliNumber++;
381   auto cb = []( void* data )
382   {
383     TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
384     if ( !LWE::LWE::IsInitialized() )
385     {
386       LWE::LWE::Initialize("/tmp/StarFish_localStorage.txt",
387                            "/tmp/StarFish_Cookies.txt", "/tmp/StarFish-cache");
388     }
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 )
394         {
395           engine->onRenderedHandler( container, renderResult );
396         } );
397     TO_CONTAINER( data )->RegisterOnReceivedErrorHandler(
398         [ engine ]( LWE::WebContainer* container, LWE::ResourceError error )
399         {
400           engine->mCanGoBack = container->CanGoBack();
401           engine->mCanGoForward = container->CanGoForward();
402           engine->onReceivedError( container, error );
403         });
404     TO_CONTAINER( data )->RegisterOnPageStartedHandler(
405         [ engine ]( LWE::WebContainer* container, const std::string& url )
406         {
407           engine->mUrl = url;
408           engine->mCanGoBack = container->CanGoBack();
409           engine->mCanGoForward = container->CanGoForward();
410           engine->onPageStartedHandler( container, url );
411         });
412     TO_CONTAINER( data )->RegisterOnPageLoadedHandler(
413         [ engine ]( LWE::WebContainer* container, const std::string& url )
414         {
415           engine->mUrl = url;
416           engine->mCanGoBack = container->CanGoBack();
417           engine->mCanGoForward = container->CanGoForward();
418           engine->onPageFinishedHandler( container, url );
419         });
420     TO_CONTAINER( data )->RegisterOnLoadResourceHandler(
421         [ engine ]( LWE::WebContainer* container, const std::string& url )
422         {
423           engine->mUrl = url;
424           engine->mCanGoBack = container->CanGoBack();
425           engine->mCanGoForward = container->CanGoForward();
426           engine->onLoadResourceHandler( container, url );
427         });
428     };
429     SendAsyncHandle( cb );
430 }
431
432 void TizenWebEngineLite::Create( int width, int height, const std::string& locale, const std::string& timezoneId )
433 {
434   mTimer = Dali::Timer::New( TIMER_INTERVAL );
435   mTimer.TickSignal().Connect( this, &TizenWebEngineLite::UpdateBuffer );
436   mTimer.Start();
437
438   StartMainThreadIfNeeds();
439
440   mIsRunning = true;
441   mOutputWidth = width;
442   mOutputHeight = height;
443   mOutputStride = width * sizeof( uint32_t );
444   mOutputBuffer = ( uint8_t* )malloc( width * height * sizeof( uint32_t ) );
445
446   if( gIsFirstTime == true )
447   {
448     gIsFirstTime = false;
449
450     onRenderedHandler = [this]( LWE::WebContainer* c, const LWE::WebContainer::RenderResult& renderResult )
451     {
452       Locker l( gMutex );
453       size_t w = mOutputWidth;
454       size_t h = mOutputHeight;
455       if( renderResult.updatedWidth != w || renderResult.updatedHeight != h )
456       {
457         return;
458       }
459
460       uint8_t* dstBuffer;
461       size_t dstStride;
462
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 )
466       {
467         DALI_LOG_ERROR( "Fail to map tbm_surface\n" );
468       }
469
470       DALI_ASSERT_ALWAYS( tbmSurfaceInfo.format == TBM_FORMAT_ABGR8888 && "Unsupported TizenWebEngineLite tbm format" );
471
472       dstBuffer = tbmSurfaceInfo.planes[0].ptr;
473       dstStride = tbmSurfaceInfo.planes[0].stride;
474
475 #else
476       dstBuffer = mBufferImage.GetBuffer();
477       dstStride = mBufferImage.GetBufferStride();
478 #endif
479
480       uint32_t srcStride = renderResult.updatedWidth * sizeof(uint32_t);
481       uint8_t* srcBuffer = static_cast< uint8_t* >( renderResult.updatedBufferAddress );
482
483       if (dstStride == srcStride)
484       {
485         memcpy( dstBuffer, srcBuffer, tbmSurfaceInfo.planes[0].size );
486       }
487       else
488       {
489         for ( auto y = renderResult.updatedY; y < ( renderResult.updatedHeight + renderResult.updatedY ); y++ )
490         {
491           auto start = renderResult.updatedX;
492           memcpy( dstBuffer + ( y * dstStride ) + ( start * 4 ), srcBuffer + ( y * srcStride ) + ( start * 4 ), srcStride );
493         }
494       }
495
496 #ifdef STARFISH_DALI_TBMSURFACE
497       if( tbm_surface_unmap( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
498       {
499         DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
500       }
501 #endif
502       gIsNeedsUpdate = true;
503     };
504
505     onReceivedError = []( LWE::WebContainer* container, LWE::ResourceError error ) {
506     };
507     onPageStartedHandler = []( LWE::WebContainer* container, const std::string& url ) {
508     };
509     onPageFinishedHandler = []( LWE::WebContainer* container, const std::string& url ) {
510     };
511     onLoadResourceHandler = []( LWE::WebContainer* container, const std::string& url ) {
512     };
513   }
514
515 #ifdef STARFISH_DALI_TBMSURFACE
516   mTbmSurface = tbm_surface_create( width, height, TBM_FORMAT_ABGR8888 );
517   mNativeImageSourcePtr = Dali::NativeImageSource::New( mTbmSurface );
518 #else
519   mBufferImage = Dali::BufferImage::New( width, height, Dali::Pixel::RGBA8888 );
520 #endif
521
522   CreateInstance();
523   while ( true )
524   {
525       if ( mWebContainer )
526       {
527           break;
528       }
529       usleep( 100 );
530   }
531 }
532
533 void TizenWebEngineLite::Destroy()
534 {
535   if( !mWebContainer )
536   {
537     return;
538   }
539
540   if( mIsRunning == true )
541   {
542     mIsRunning = false;
543
544 #ifdef STARFISH_DALI_TBMSURFACE
545     if( mTbmSurface != NULL && tbm_surface_destroy( mTbmSurface ) != TBM_SURFACE_ERROR_NONE )
546     {
547       DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
548     }
549 #endif
550
551     DestroyInstance();
552     StopLoop();
553
554     int status;
555     pthread_join( mThreadHandle, ( void** )&status );
556
557     mWebContainer = NULL;
558   }
559 }
560
561 void TizenWebEngineLite::DestroyInstance()
562 {
563         DALI_ASSERT_ALWAYS( mWebContainer );
564         auto cb = []( void* data )
565         {
566           TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
567
568           TO_CONTAINER( data )->Destroy();
569
570           while ( !engine->mAsyncHandlePool.empty() )
571           {
572             UVAsyncHandleData* handleData = NULL;
573             {
574               Locker l( gMutex );
575               handleData = ( UVAsyncHandleData* )*engine->mAsyncHandlePool.begin();
576               engine->mAsyncHandlePool.erase( engine->mAsyncHandlePool.begin() );
577             }
578
579             if ( handleData ) {
580               handleData->cb( handleData->data );
581               delete handleData;
582             }
583           }
584           gDaliNumber--;
585         };
586         SendAsyncHandle( cb );
587 }
588
589 Dali::NativeImageInterfacePtr TizenWebEngineLite::GetNativeImageSource()
590 {
591   return mNativeImageSourcePtr;
592 }
593
594 void TizenWebEngineLite::LoadUrl( const std::string& url )
595 {
596   DALI_ASSERT_ALWAYS( mWebContainer );
597   auto cb = [url]( void* data )
598   {
599     TO_CONTAINER( data )->LoadURL( url );
600   };
601   SendAsyncHandle( cb );
602 }
603
604 const std::string& TizenWebEngineLite::GetUrl()
605 {
606   DALI_ASSERT_ALWAYS( mWebContainer );
607   return mUrl;
608 }
609
610 void TizenWebEngineLite::LoadHTMLString( const std::string& str )
611 {
612   DALI_ASSERT_ALWAYS( mWebContainer );
613   auto cb = [str]( void* data )
614   {
615     TO_CONTAINER( data )->LoadData( str );
616   };
617   SendAsyncHandle( cb );
618 }
619
620 void TizenWebEngineLite::Reload()
621 {
622   DALI_ASSERT_ALWAYS( mWebContainer );
623   auto cb = []( void* data )
624   {
625     TO_CONTAINER( data )->Reload();
626   };
627   SendAsyncHandle( cb );
628 }
629
630 void TizenWebEngineLite::StopLoading()
631 {
632   DALI_ASSERT_ALWAYS( mWebContainer );
633   auto cb = []( void* data )
634   {
635     TO_CONTAINER( data )->StopLoading();
636   };
637   SendAsyncHandle( cb );
638 }
639
640 void TizenWebEngineLite::GoBack()
641 {
642   DALI_ASSERT_ALWAYS( mWebContainer );
643   auto cb = []( void* data )
644   {
645     TO_CONTAINER( data )->GoBack();
646   };
647   SendAsyncHandle( cb );
648 }
649
650 void TizenWebEngineLite::GoForward()
651 {
652   DALI_ASSERT_ALWAYS( mWebContainer );
653   auto cb = []( void* data )
654   {
655     TO_CONTAINER( data )->GoForward();
656   };
657   SendAsyncHandle( cb );
658 }
659
660 bool TizenWebEngineLite::CanGoBack()
661 {
662   DALI_ASSERT_ALWAYS( mWebContainer );
663   return mCanGoBack;
664 }
665
666 bool TizenWebEngineLite::CanGoForward()
667 {
668   DALI_ASSERT_ALWAYS( mWebContainer );
669   return mCanGoForward;
670 }
671
672 void TizenWebEngineLite::EvaluateJavaScript( const std::string& script )
673 {
674   DALI_ASSERT_ALWAYS( mWebContainer );
675   auto cb = [script]( void* data ) {
676       TO_CONTAINER( data )->EvaluateJavaScript( script );
677   };
678   SendAsyncHandle( cb );
679 }
680
681 void TizenWebEngineLite::AddJavaScriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName, std::function< std::string(const std::string&) > callback )
682 {
683   DALI_ASSERT_ALWAYS( mWebContainer );
684   auto cb = [exposedObjectName, jsFunctionName, callback]( void* data )
685   {
686     TO_CONTAINER( data )->AddJavaScriptInterface( exposedObjectName, jsFunctionName, callback );
687   };
688   SendAsyncHandle( cb );
689 }
690
691 void TizenWebEngineLite::RemoveJavascriptInterface( const std::string& exposedObjectName, const std::string& jsFunctionName )
692 {
693   DALI_ASSERT_ALWAYS( mWebContainer );
694   auto cb = [exposedObjectName, jsFunctionName]( void* data )
695   {
696     TO_CONTAINER( data )->RemoveJavascriptInterface( exposedObjectName, jsFunctionName );
697   };
698   SendAsyncHandle( cb );
699 }
700
701 void TizenWebEngineLite::ClearHistory()
702 {
703   DALI_ASSERT_ALWAYS( mWebContainer );
704   auto cb = []( void* data )
705   {
706     TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
707     TO_CONTAINER( data )->ClearHistory();
708     engine->mCanGoBack = TO_CONTAINER( data )->CanGoBack();
709   };
710   SendAsyncHandle( cb );
711 }
712
713 void TizenWebEngineLite::ClearCache()
714 {
715   DALI_ASSERT_ALWAYS( mWebContainer );
716   auto cb = []( void* data )
717   {
718     TO_CONTAINER( data )->ClearCache();
719   };
720   SendAsyncHandle( cb );
721 }
722
723 void TizenWebEngineLite::SetSize( int width, int height )
724 {
725   DALI_ASSERT_ALWAYS( mWebContainer );
726
727   if( mOutputWidth != ( size_t )width || mOutputHeight != ( size_t )height )
728   {
729     Locker l( gMutex );
730           mOutputWidth = width;
731           mOutputHeight = height;
732           mOutputStride = width * sizeof(uint32_t);
733
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 )
740           {
741                   DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
742           }
743 #endif
744
745           auto cb = []( void* data )
746     {
747             TizenWebEngineLite* engine = static_cast< TizenWebEngineLite* >( data );
748
749             Locker l( gMutex );
750             if (engine->mOutputBuffer) {
751               free(engine->mOutputBuffer);
752               engine->mOutputBuffer = NULL;
753             }
754
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 );
759           };
760           SendAsyncHandle( cb );
761   }
762 }
763
764 void TizenWebEngineLite::DispatchMouseDownEvent( float x, float y )
765 {
766         DALI_ASSERT_ALWAYS( mWebContainer );
767         if (!mIsRunning)
768         {
769           return;
770         }
771
772         auto cb = [x, y]( void* data )
773   {
774           TO_CONTAINER( data )->DispatchMouseDownEvent( LWE::MouseButtonValue::LeftButton, LWE::MouseButtonsValue::LeftButtonDown, x, y );
775   };
776         SendAsyncHandle( cb );
777 }
778
779 void TizenWebEngineLite::DispatchMouseUpEvent( float x, float y )
780 {
781   DALI_ASSERT_ALWAYS( mWebContainer );
782   if (!mIsRunning)
783   {
784     return;
785   }
786
787   auto cb = [x, y]( void* data )
788   {
789     TO_CONTAINER( data )->DispatchMouseUpEvent( LWE::MouseButtonValue::NoButton, LWE::MouseButtonsValue::NoButtonDown, x, y );
790   };
791   SendAsyncHandle( cb );
792 }
793
794 void TizenWebEngineLite::DispatchMouseMoveEvent( float x, float y, bool isLButtonPressed, bool isRButtonPressed )
795 {
796         DALI_ASSERT_ALWAYS( mWebContainer );
797         if (!mIsRunning)
798         {
799           return;
800         }
801
802         auto cb = [x, y, isLButtonPressed]( void* data )
803   {
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 );
809   };
810         SendAsyncHandle( cb );
811 }
812
813 bool TizenWebEngineLite::SendTouchEvent( const TouchData& touch )
814 {
815   size_t pointCount = touch.GetPointCount();
816   if( pointCount == 1 )
817   {
818     // Single touch event
819     Dali::PointState::Type pointState = touch.GetState( 0 );
820     const Dali::Vector2& screen = touch.GetLocalPosition( 0 );
821
822     if( pointState == Dali::PointState::DOWN )
823     {
824       DispatchMouseDownEvent( screen.x, screen.y );
825       mIsMouseLbuttonDown = true;
826     }
827     else if( pointState == Dali::PointState::UP )
828     {
829       DispatchMouseUpEvent( screen.x, screen.y );
830       mIsMouseLbuttonDown = false;
831     }
832     else
833     {
834       DispatchMouseMoveEvent( screen.x, screen.y, mIsMouseLbuttonDown, false );
835     }
836   }
837
838   return false;
839 }
840
841 void TizenWebEngineLite::DispatchKeyDownEvent( LWE::KeyValue keyCode )
842 {
843         DALI_ASSERT_ALWAYS( mWebContainer );
844         if (!mIsRunning)
845         {
846           return;
847         }
848
849         auto cb = [keyCode]( void* data )
850   {
851           TO_CONTAINER( data )->DispatchKeyDownEvent( keyCode );
852   };
853         SendAsyncHandle( cb );
854 }
855
856 void TizenWebEngineLite::DispatchKeyPressEvent( LWE::KeyValue keyCode )
857 {
858         DALI_ASSERT_ALWAYS( mWebContainer );
859         if (!mIsRunning)
860         {
861           return;
862         }
863
864         auto cb = [keyCode]( void* data )
865   {
866           TO_CONTAINER( data )->DispatchKeyPressEvent( keyCode );
867   };
868         SendAsyncHandle( cb );
869 }
870
871 void TizenWebEngineLite::DispatchKeyUpEvent( LWE::KeyValue keyCode )
872 {
873         DALI_ASSERT_ALWAYS( mWebContainer );
874         if (!mIsRunning)
875         {
876           return;
877         }
878
879         auto cb = [keyCode]( void* data )
880   {
881           TO_CONTAINER( data )->DispatchKeyUpEvent(keyCode);
882   };
883         SendAsyncHandle( cb );
884 }
885
886 bool TizenWebEngineLite::SendKeyEvent( const Dali::KeyEvent& event )
887 {
888   LWE::KeyValue keyValue = LWE::KeyValue::UnidentifiedKey;
889   if( 32 < event.keyPressed.c_str()[0] && 127 > event.keyPressed.c_str()[0] )
890   {
891     keyValue = static_cast<LWE::KeyValue>(event.keyPressed.c_str()[0]);
892   }
893   else
894   {
895     keyValue = KeyStringToKeyValue( event.keyPressedName.c_str(), event.keyModifier & 1 );
896   }
897   if( event.state == Dali::KeyEvent::Down )
898   {
899     DispatchKeyDownEvent( keyValue );
900     DispatchKeyPressEvent( keyValue );
901   }
902   else if( event.state == Dali::KeyEvent::Up )
903   {
904     DispatchKeyUpEvent( keyValue );
905   }
906
907   return false;
908 }
909
910 void TizenWebEngineLite::CallEmptyAsyncHandle()
911 {
912         DALI_ASSERT_ALWAYS( mWebContainer );
913         auto cb = []( void* data ) {
914   };
915         SendAsyncHandle( cb );
916 }
917
918 void TizenWebEngineLite::StopLoop()
919 {
920   gDaliNumber = -1;
921   CallEmptyAsyncHandle();
922 }
923
924 void TizenWebEngineLite::SendAsyncHandle(std::function<void(void*)> cb)
925 {
926   UVAsyncHandleData* handle = new UVAsyncHandleData();
927   handle->cb = cb;
928   handle->data = this;
929
930   {
931     Locker l( gMutex );
932     mAsyncHandlePool.push_back( ( size_t )handle );
933   }
934
935   gLauncherHandle.data = this;
936   uv_async_send(&gLauncherHandle);
937 }
938
939 void* TizenWebEngineLite::StartMainThread( void* data )
940 {
941   uv_async_init( uv_default_loop(), &gLauncherHandle, []( uv_async_t* handle )
942   {
943     Dali::Plugin::TizenWebEngineLite* engine = static_cast< Dali::Plugin::TizenWebEngineLite* >(handle->data);
944     while ( !engine->mAsyncHandlePool.empty() )
945     {
946       UVAsyncHandleData* handleData = NULL;
947       {
948         Locker l( gMutex );
949         handleData = ( UVAsyncHandleData* )*engine->mAsyncHandlePool.begin();
950         engine->mAsyncHandlePool.erase( engine->mAsyncHandlePool.begin() );
951       }
952
953       if ( handleData )
954       {
955         handleData->cb( handleData->data );
956         delete handleData;
957       }
958     }
959   });
960
961   gIsAliveMainLoop = true;
962   pthread_mutex_unlock( &gMutex );
963   while ( true )
964   {
965     uv_run( uv_default_loop(), UV_RUN_ONCE );
966     if ( gDaliNumber < 0 )
967     {
968       break;
969     }
970   }
971   return NULL;
972 }
973
974 } // namespace Plugin
975 } // namespace Dali