[Tizen] Support custom fonts registration
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / tizen-wayland / indicator-impl-ecore-wl.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 <dali/internal/window-system/tizen-wayland/indicator-impl-ecore-wl.h>
20
21 // EXTERNAL INCLUDES
22 // Ecore is littered with C style cast
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wold-style-cast"
25 #include <Ecore.h>
26 #include <Evas.h>
27
28 #ifdef ECORE_WAYLAND2
29 #include <Ecore_Wl2.h>
30 #else
31 #include <Ecore_Wayland.h>
32 #endif
33
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38
39 #include <dali/public-api/images/native-image.h>
40 #include <dali/public-api/events/touch-point.h>
41 #include <dali/public-api/common/stage.h>
42 #include <dali/public-api/images/pixel.h>
43
44 #include <dali/integration-api/debug.h>
45
46 // INTERNAL INCLUDES
47 #include <dali/internal/adaptor/common/adaptor-impl.h>
48 #include <dali/internal/accessibility/common/accessibility-adaptor-impl.h>
49 #include <dali/public-api/adaptor-framework/native-image-source.h>
50
51 #if defined(DEBUG_ENABLED)
52 #define STATE_DEBUG_STRING(state) (state==DISCONNECTED?"DISCONNECTED":state==CONNECTED?"CONNECTED":"UNKNOWN")
53 #endif
54
55 namespace
56 {
57
58 const float SLIDING_ANIMATION_DURATION( 0.2f ); // 200 milli seconds
59 const float AUTO_INDICATOR_STAY_DURATION( 3.0f ); // 3 seconds
60
61 enum
62 {
63   KEEP_SHOWING = -1,
64   HIDE_NOW = 0
65 };
66
67 const int NUM_GRADIENT_INTERVALS(5); // Number of gradient intervals
68 const float GRADIENT_ALPHA[NUM_GRADIENT_INTERVALS+1] = { 0.6f, 0.38f, 0.20f, 0.08f, 0.0f, 0.0f };
69
70 #define MAKE_SHADER(A)#A
71
72 const char* BACKGROUND_VERTEX_SHADER = MAKE_SHADER(
73   attribute mediump vec2 aPosition;
74   attribute mediump float aAlpha;
75   varying mediump float vAlpha;
76   uniform mediump mat4 uMvpMatrix;
77   uniform mediump vec3 uSize;
78
79   void main()
80   {
81     mediump vec4 vertexPosition = vec4( aPosition * uSize.xy, 0.0, 1.0 );
82     vertexPosition = uMvpMatrix * vertexPosition;
83
84     vAlpha = aAlpha;
85     gl_Position = vertexPosition;
86   }
87 );
88
89 const char* BACKGROUND_FRAGMENT_SHADER = MAKE_SHADER(
90   uniform lowp vec4 uColor;
91   varying mediump float vAlpha;
92
93   void main()
94   {
95     gl_FragColor = uColor;
96     gl_FragColor.a *= vAlpha;
97   }
98 );
99
100 const char* FOREGROUND_VERTEX_SHADER = DALI_COMPOSE_SHADER(
101   attribute mediump vec2 aPosition;\n
102   varying mediump vec2 vTexCoord;\n
103   uniform mediump mat4 uMvpMatrix;\n
104   uniform mediump vec3 uSize;\n
105   uniform mediump vec4 sTextureRect;\n
106   \n
107   void main()\n
108   {\n
109     gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n
110     vTexCoord = aPosition + vec2(0.5);\n
111   }\n
112 );
113
114 const char* FOREGROUND_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
115   varying mediump vec2 vTexCoord;\n
116   uniform sampler2D sTexture;\n
117   \n
118   void main()\n
119   {\n
120     gl_FragColor = texture2D( sTexture, vTexCoord );\n // the foreground does not apply actor color
121   }\n
122 );
123
124 Dali::Geometry CreateQuadGeometry()
125 {
126   Dali::Property::Map quadVertexFormat;
127   quadVertexFormat["aPosition"] = Dali::Property::VECTOR2;
128   Dali::PropertyBuffer vertexData = Dali::PropertyBuffer::New( quadVertexFormat );
129
130   const float halfQuadSize = .5f;
131   struct QuadVertex { Dali::Vector2 position; };
132   QuadVertex quadVertexData[4] = {
133       { Dali::Vector2(-halfQuadSize, -halfQuadSize) },
134       { Dali::Vector2(-halfQuadSize, halfQuadSize) },
135       { Dali::Vector2( halfQuadSize, -halfQuadSize) },
136       { Dali::Vector2( halfQuadSize, halfQuadSize) } };
137   vertexData.SetData(quadVertexData, 4);
138
139   Dali::Geometry quad = Dali::Geometry::New();
140   quad.AddVertexBuffer( vertexData );
141   quad.SetType( Dali::Geometry::TRIANGLE_STRIP );
142   return quad;
143 }
144
145 // indicator service name
146 const char* INDICATOR_SERVICE_NAME("elm_indicator");
147
148 // Copied from ecore_evas_extn_engine.h
149
150 enum // opcodes
151 {
152    OP_RESIZE,
153    OP_SHOW,
154    OP_HIDE,
155    OP_FOCUS,
156    OP_UNFOCUS,
157    OP_UPDATE,
158    OP_UPDATE_DONE,
159    OP_SHM_REF0,
160    OP_SHM_REF1,
161    OP_SHM_REF2,
162    OP_PROFILE_CHANGE_REQUEST,
163    OP_PROFILE_CHANGE_DONE,
164    OP_EV_MOUSE_IN,
165    OP_EV_MOUSE_OUT,
166    OP_EV_MOUSE_UP,
167    OP_EV_MOUSE_DOWN,
168    OP_EV_MOUSE_MOVE,
169    OP_EV_MOUSE_WHEEL,
170    OP_EV_MULTI_UP,
171    OP_EV_MULTI_DOWN,
172    OP_EV_MULTI_MOVE,
173    OP_EV_KEY_UP,
174    OP_EV_KEY_DOWN,
175    OP_EV_HOLD,
176    OP_MSG_PARENT,
177    OP_MSG,
178 };
179
180 // Copied from elm_conform.c
181
182 const int MSG_DOMAIN_CONTROL_INDICATOR( 0x10001 );
183 const int MSG_ID_INDICATOR_REPEAT_EVENT( 0x10002 );
184 const int MSG_ID_INDICATOR_ROTATION( 0x10003 );
185 const int MSG_ID_INDICATOR_OPACITY( 0X1004 );
186 const int MSG_ID_INDICATOR_TYPE( 0X1005 );
187 const int MSG_ID_INDICATOR_START_ANIMATION( 0X10006 );
188
189 struct IpcDataResize
190 {
191   int w, h;
192 };
193
194 struct IpcIndicatorDataAnimation
195 {
196   unsigned int xwin;
197   double       duration;
198 };
199
200 struct IpcDataEvMouseUp
201 {
202   int               b;
203   Evas_Button_Flags flags;
204   int               mask;
205   unsigned int      timestamp;
206   Evas_Event_Flags  event_flags;
207
208   IpcDataEvMouseUp(unsigned long timestamp)
209   : b(1),
210     flags(EVAS_BUTTON_NONE),
211     mask(0),
212     timestamp(static_cast<unsigned int>(timestamp)),
213     event_flags(EVAS_EVENT_FLAG_NONE)
214   {
215   }
216 };
217
218 struct IpcDataEvMouseDown
219 {
220   int                b;
221   Evas_Button_Flags  flags;
222   int                mask;
223   unsigned int       timestamp;
224   Evas_Event_Flags   event_flags;
225
226   IpcDataEvMouseDown(unsigned long timestamp)
227   : b(1),
228     flags(EVAS_BUTTON_NONE),
229     mask(0),
230     timestamp(static_cast<unsigned int>(timestamp)),
231     event_flags(EVAS_EVENT_FLAG_NONE)
232   {
233   }
234 };
235
236 struct IpcDataEvMouseMove
237 {
238   int                x, y;
239   Evas_Button_Flags  flags;
240   int                mask;
241   unsigned int       timestamp;
242   Evas_Event_Flags   event_flags;
243
244   IpcDataEvMouseMove(const Dali::Vector2& touchPoint, unsigned long timestamp)
245   : x(static_cast<Evas_Coord>(touchPoint.x)),
246     y(static_cast<Evas_Coord>(touchPoint.y)),
247     flags(EVAS_BUTTON_NONE),
248     mask(0),
249     timestamp(static_cast<unsigned int>(timestamp)),
250     event_flags(EVAS_EVENT_FLAG_NONE)
251   {
252   }
253 };
254
255 struct IpcDataEvMouseOut
256 {
257   unsigned int     timestamp;
258   int              mask;
259   Evas_Event_Flags event_flags;
260
261   IpcDataEvMouseOut(unsigned long timestamp)
262   : timestamp(static_cast<unsigned int>(timestamp)),
263     mask(0),
264     event_flags(EVAS_EVENT_FLAG_NONE)
265   {
266   }
267 };
268
269 #ifdef ENABLE_INDICATOR_IMAGE_SAVING
270
271 void SaveIndicatorImage( Dali::NativeImageSourcePtr nativeImageSource )
272 {
273   // Save image data to disk in BMP form.
274   static int gFilenameCounter = 0;
275   static const char bmpHeader[] = {
276       0x42, 0x4d, 0x0a, 0xcb, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x7c, 0x00,
277       0x00, 0x00,
278       0xe0, 0x01, 0x00, 0x00, // Width  (480)
279       0x1b, 0x00, 0x00, 0x00, // Height ( 27)
280       0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
281       0x00, 0x00, 0x80, 0xca, 0x00, 0x00, 0x13, 0x0b,  0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
282       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
283       0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x42, 0x47,  0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
287       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00
288     };
289
290   // This is a BMP header with width & height hard-coded in.
291   // The data was first determined by dumping the raw data and inspecting in GIMP, before creating this header data.
292   std::vector<unsigned char> buffer;
293   unsigned int w = 0;
294   unsigned int h = 0;
295   Dali::Pixel::Format pixelFormat;
296   if( nativeImageSource->GetPixels( buffer, w, h, pixelFormat ) )
297   {
298     int imageSize = w * h * 4;
299     std::stringstream fileName;
300     // Give each file an incremental filename.
301     fileName << "/opt/usr/media/Images/out-" << std::setfill( '0' ) << std::setw( 5 ) << gFilenameCounter << ".bmp";
302
303     std::ofstream outfile( fileName.str().c_str(), std::ofstream::binary );
304     if( outfile.is_open() )
305     {
306       DALI_LOG_WARNING( "Saving Indicator Image w:%d, h:%d, %s\n", w, h, fileName.str().c_str() );
307
308       outfile.write( bmpHeader, sizeof( bmpHeader ) / sizeof( bmpHeader[0] ) ); // Size of the BMP header.
309       outfile.write( (const char*)buffer.data(), imageSize );
310       outfile.close();
311       gFilenameCounter++;
312     }
313     else
314     {
315       DALI_LOG_ERROR( "COULD NOT OPEN FOR SAVING: %s\n", fileName.str().c_str() );
316     }
317   }
318 }
319
320 #endif
321
322 } // anonymous namespace
323
324
325 namespace Dali
326 {
327 namespace Internal
328 {
329 namespace Adaptor
330 {
331 #if defined(DEBUG_ENABLED)
332 Debug::Filter* gIndicatorLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_INDICATOR");
333 #endif
334
335 // Impl to hide EFL implementation.
336
337 struct IndicatorEcoreWl::Impl
338 {
339   enum // operation mode
340   {
341     INDICATOR_HIDE,
342     INDICATOR_STAY_WITH_DURATION
343   };
344
345   /**
346    * Constructor
347    */
348   Impl(IndicatorEcoreWl* indicator)
349   : mIndicator(indicator),
350     mEcoreEventHandler(NULL)
351   {
352 #if defined(DALI_PROFILE_MOBILE)
353 #ifdef ECORE_WAYLAND2
354     mEcoreEventHandler = ecore_event_handler_add(ECORE_WL2_EVENT_INDICATOR_FLICK,  EcoreEventIndicator, this);
355 #else
356     mEcoreEventHandler = ecore_event_handler_add(ECORE_WL_EVENT_INDICATOR_FLICK,  EcoreEventIndicator, this);
357 #endif
358 #endif // DALI_PROFILE_MOBILE
359   }
360
361   /**
362    * Destructor
363    */
364   ~Impl()
365   {
366     if ( mEcoreEventHandler )
367     {
368       ecore_event_handler_del(mEcoreEventHandler);
369     }
370   }
371
372   static void SetIndicatorVisibility( void* data, int operation )
373   {
374     IndicatorEcoreWl::Impl* indicatorImpl((IndicatorEcoreWl::Impl*)data);
375
376     if ( indicatorImpl == NULL || indicatorImpl->mIndicator == NULL)
377     {
378       return;
379     }
380     if ( operation == INDICATOR_STAY_WITH_DURATION )
381     {
382       // if indicator is not showing, INDICATOR_FLICK_DONE is given
383       if( indicatorImpl->mIndicator->mVisible == Dali::Window::AUTO &&
384           !indicatorImpl->mIndicator->mIsShowing )
385       {
386         indicatorImpl->mIndicator->ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
387       }
388     }
389     else if( operation == INDICATOR_HIDE )
390     {
391       if( indicatorImpl->mIndicator->mVisible == Dali::Window::AUTO &&
392           indicatorImpl->mIndicator->mIsShowing )
393       {
394         indicatorImpl->mIndicator->ShowIndicator( HIDE_NOW );
395       }
396     }
397   }
398
399 #if defined(DALI_PROFILE_MOBILE)
400   /**
401    * Called when the Ecore indicator event is received.
402    */
403   static Eina_Bool EcoreEventIndicator( void* data, int type, void* event )
404   {
405     SetIndicatorVisibility( data, INDICATOR_STAY_WITH_DURATION );
406     return ECORE_CALLBACK_PASS_ON;
407   }
408 #endif // DALI_PROFILE_MOBILE
409
410   // Data
411   IndicatorEcoreWl*    mIndicator;
412   Ecore_Event_Handler* mEcoreEventHandler;
413 };
414
415 IndicatorEcoreWl::LockFile::LockFile(const std::string filename)
416 : mFilename(filename),
417   mErrorThrown(false)
418 {
419   mFileDescriptor = open(filename.c_str(), O_RDWR);
420   if( mFileDescriptor == -1 )
421   {
422     mFileDescriptor = 0;
423     mErrorThrown = true;
424     DALI_LOG_ERROR( "### Cannot open %s for indicator lock ###\n", mFilename.c_str() );
425   }
426 }
427
428 IndicatorEcoreWl::LockFile::~LockFile()
429 {
430   // Closing file descriptor also unlocks file.
431   if( mFileDescriptor > 0 )
432   {
433     close( mFileDescriptor );
434   }
435 }
436
437 bool IndicatorEcoreWl::LockFile::Lock()
438 {
439   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
440
441   bool locked = false;
442   if( mFileDescriptor > 0 )
443   {
444     struct flock filelock;
445
446     filelock.l_type = F_RDLCK;
447     filelock.l_whence = SEEK_SET;
448     filelock.l_start = 0;
449     filelock.l_len = 0;
450     if( fcntl( mFileDescriptor, F_SETLKW, &filelock ) == -1 )
451     {
452       mErrorThrown = true;
453       DALI_LOG_ERROR( "### Failed to lock with fd : %s ###\n", mFilename.c_str() );
454     }
455     else
456     {
457       locked = true;
458     }
459   }
460   else
461   {
462     mErrorThrown = true;
463     DALI_LOG_ERROR( "### Invalid fd ###\n" );
464   }
465
466   return locked;
467 }
468
469 void IndicatorEcoreWl::LockFile::Unlock()
470 {
471   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
472
473   if( mFileDescriptor > 0 )
474   {
475     struct flock filelock;
476
477     filelock.l_type = F_UNLCK;
478     filelock.l_whence = SEEK_SET;
479     filelock.l_start = 0;
480     filelock.l_len = 0;
481     if (fcntl(mFileDescriptor, F_SETLKW, &filelock) == -1)
482     {
483       mErrorThrown = true;
484       DALI_LOG_ERROR( "### Failed to lock with fd : %s ###\n", mFilename.c_str() );
485     }
486   }
487 }
488
489 bool IndicatorEcoreWl::LockFile::RetrieveAndClearErrorStatus()
490 {
491   bool error = mErrorThrown;
492   mErrorThrown = false;
493   return error;
494 }
495
496 IndicatorEcoreWl::ScopedLock::ScopedLock(LockFile* lockFile)
497 : mLockFile(lockFile),
498   mLocked(false)
499 {
500   if(mLockFile)
501   {
502     mLocked = mLockFile->Lock();
503   }
504 }
505
506 IndicatorEcoreWl::ScopedLock::~ScopedLock()
507 {
508   if( mLockFile )
509   {
510     mLockFile->Unlock();
511   }
512 }
513
514 bool IndicatorEcoreWl::ScopedLock::IsLocked()
515 {
516   return mLocked;
517 }
518
519 IndicatorEcoreWl::IndicatorEcoreWl( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, IndicatorInterface::Observer* observer )
520 : mConnection( this ),
521   mOpacityMode( Dali::Window::OPAQUE ),
522   mState( DISCONNECTED ),
523   mAdaptor(adaptor),
524   mServerConnection( NULL ),
525   mObserver( observer ),
526   mOrientation( orientation ),
527   mImageWidth( 0 ),
528   mImageHeight( 0 ),
529   mVisible( Dali::Window::INVISIBLE ),
530   mIsShowing( true ),
531   mIsAnimationPlaying( false ),
532   mCurrentSharedFile( 0 ),
533   mImpl( NULL ),
534   mBackgroundVisible( false ),
535   mTopMargin( 0 )
536 {
537   mIndicatorContentActor = Dali::Actor::New();
538   mIndicatorContentActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
539   mIndicatorContentActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
540
541   // Indicator image handles the touch event including "leave"
542   mIndicatorContentActor.SetLeaveRequired( true );
543   mIndicatorContentActor.TouchSignal().Connect( this, &IndicatorEcoreWl::OnTouch );
544   mIndicatorContentActor.SetColor( Color::BLACK );
545
546   mIndicatorActor = Dali::Actor::New();
547   mIndicatorActor.Add( mIndicatorContentActor );
548
549   // Event handler to find out flick down gesture
550   mEventActor = Dali::Actor::New();
551   mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
552   mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
553   mIndicatorActor.Add( mEventActor );
554
555   // Attach pan gesture to find flick down during hiding.
556   // It can prevent the problem that scrollview gets pan gesture even indicator area is touched,
557   // since it consumes the pan gesture in advance.
558   mPanDetector = Dali::PanGestureDetector::New();
559   mPanDetector.DetectedSignal().Connect( this, &IndicatorEcoreWl::OnPan );
560   mPanDetector.Attach( mEventActor );
561
562   Open( orientation );
563
564   // register indicator to accessibility adaptor
565   Dali::AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
566   if(accessibilityAdaptor)
567   {
568     AccessibilityAdaptor::GetImplementation( accessibilityAdaptor ).SetIndicator( this );
569   }
570   // hide the indicator by default
571   mIndicatorActor.SetVisible( false );
572
573   // create impl to handle ecore event
574   mImpl = new Impl(this);
575 }
576
577 IndicatorEcoreWl::~IndicatorEcoreWl()
578 {
579   if(mImpl)
580   {
581     delete mImpl;
582     mImpl = NULL;
583   }
584
585   if(mEventActor)
586   {
587     mEventActor.TouchSignal().Disconnect( this, &IndicatorEcoreWl::OnTouch );
588   }
589   Disconnect();
590 }
591
592 void IndicatorEcoreWl::SetAdaptor(Adaptor* adaptor)
593 {
594   mAdaptor = adaptor;
595   mIndicatorBuffer->SetAdaptor( adaptor );
596 }
597
598 Dali::Actor IndicatorEcoreWl::GetActor()
599 {
600   return mIndicatorActor;
601 }
602
603 void IndicatorEcoreWl::Open( Dali::Window::WindowOrientation orientation )
604 {
605   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
606
607   // Calls from Window should be set up to ensure we are in a
608   // disconnected state before opening a second time.
609   DALI_ASSERT_DEBUG( mState == DISCONNECTED );
610
611   mOrientation = orientation;
612
613   Connect();
614
615   // Change background visibility depending on orientation
616   if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE  )
617   {
618     if( mBackgroundRenderer )
619     {
620       mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
621       mBackgroundVisible = false;
622     }
623   }
624   else
625   {
626     SetOpacityMode( mOpacityMode );
627   }
628 }
629
630 void IndicatorEcoreWl::Close()
631 {
632   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s", STATE_DEBUG_STRING(mState) );
633
634   if( mState == CONNECTED )
635   {
636     Disconnect();
637     if( mObserver != NULL )
638     {
639       mObserver->IndicatorClosed( this );
640     }
641   }
642
643   Dali::Texture emptyTexture;
644   SetForegroundImage( emptyTexture );
645 }
646
647 void IndicatorEcoreWl::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
648 {
649   mOpacityMode = mode;
650
651   Dali::Geometry geometry = CreateBackgroundGeometry();
652   if( geometry )
653   {
654     if( mBackgroundRenderer )
655     {
656       if( mBackgroundRenderer.GetGeometry() != geometry )
657       {
658         mBackgroundRenderer.SetGeometry( geometry );
659       }
660     }
661     else
662     {
663       if( !mBackgroundShader )
664       {
665         mBackgroundShader = Dali::Shader::New( BACKGROUND_VERTEX_SHADER, BACKGROUND_FRAGMENT_SHADER, Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT );
666       }
667
668       mBackgroundRenderer = Dali::Renderer::New( geometry, mBackgroundShader );
669     }
670
671     if( !mBackgroundVisible )
672     {
673       mIndicatorContentActor.AddRenderer( mBackgroundRenderer );
674       mBackgroundVisible = true;
675     }
676   }
677   else if( mBackgroundRenderer )
678   {
679     mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
680     mBackgroundVisible = false;
681   }
682   UpdateTopMargin();
683 }
684
685 void IndicatorEcoreWl::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
686 {
687   if ( visibleMode != mVisible || forceUpdate )
688   {
689     // If we were previously hidden, then we should update the image data before we display the indicator
690     if ( mVisible == Dali::Window::INVISIBLE )
691     {
692       UpdateImageData( mCurrentSharedFile );
693     }
694
695     if ( visibleMode == Dali::Window::INVISIBLE )
696     {
697       if (mServerConnection)
698       {
699         mServerConnection->SendEvent( OP_HIDE, NULL, 0 );
700       }
701     }
702     else
703     {
704       mIndicatorActor.SetVisible( true );
705
706       if( mServerConnection )
707       {
708          mServerConnection->SendEvent( OP_SHOW, NULL, 0 );
709       }
710     }
711
712     mVisible = visibleMode;
713     UpdateTopMargin();
714
715     if( mForegroundRenderer && mForegroundRenderer.GetTextures().GetTexture( 0u ) )
716     {
717       if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
718       {
719         // hide indicator
720         ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
721       }
722       else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
723       {
724         // show indicator
725         ShowIndicator( KEEP_SHOWING );
726       }
727       else
728       {
729         // hide indicator
730         ShowIndicator( HIDE_NOW );
731       }
732     }
733     else
734     {
735       mIsShowing = false;
736     }
737   }
738 }
739
740 bool IndicatorEcoreWl::IsConnected()
741 {
742   return ( mState == CONNECTED );
743 }
744
745 bool IndicatorEcoreWl::SendMessage( int messageDomain, int messageId, const void *data, int size )
746 {
747  if(IsConnected())
748  {
749    return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
750  }
751  else
752  {
753    return false;
754  }
755 }
756
757 bool IndicatorEcoreWl::OnTouch(Dali::Actor indicator, const Dali::TouchData& touchData)
758 {
759   if( mServerConnection )
760   {
761     // Send touch event to indicator server when indicator is showing
762     if( CheckVisibleState() || mIsShowing )
763     {
764       switch( touchData.GetState(0) )
765       {
766         case Dali::PointState::DOWN:
767         {
768           IpcDataEvMouseMove ipcMove( touchData.GetLocalPosition(0), touchData.GetTime() );
769           IpcDataEvMouseDown ipcDown( touchData.GetTime() );
770           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
771           mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
772
773           if( mVisible == Dali::Window::AUTO )
774           {
775             // Stop hiding indicator
776             ShowIndicator( KEEP_SHOWING );
777           }
778         }
779         break;
780
781         case Dali::PointState::MOTION:
782         {
783           IpcDataEvMouseMove ipcMove( touchData.GetLocalPosition(0), touchData.GetTime() );
784           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
785         }
786         break;
787
788         case Dali::PointState::UP:
789         case Dali::PointState::INTERRUPTED:
790         {
791           IpcDataEvMouseUp ipcUp( touchData.GetTime() );
792           mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
793
794           if( mVisible == Dali::Window::AUTO )
795           {
796             // Hide indicator
797             ShowIndicator( 0.5f /* hide after 0.5 sec */ );
798           }
799         }
800         break;
801
802         case Dali::TouchPoint::Leave:
803         {
804           IpcDataEvMouseMove ipcMove( touchData.GetLocalPosition(0), touchData.GetTime() );
805           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
806           IpcDataEvMouseUp ipcOut( touchData.GetTime() );
807           mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
808         }
809         break;
810
811         default:
812           break;
813       }
814
815       return true;
816     }
817   }
818
819   return false;
820 }
821
822 bool IndicatorEcoreWl::Connect()
823 {
824   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
825
826   DALI_ASSERT_DEBUG( mState == DISCONNECTED );
827
828   bool connected = false;
829
830   mServerConnection = new ServerConnection( INDICATOR_SERVICE_NAME, 0, false, this );
831   if( mServerConnection )
832   {
833     connected = mServerConnection->IsConnected();
834     if( ! connected )
835     {
836       delete mServerConnection;
837       mServerConnection = NULL;
838     }
839   }
840
841   if( !connected )
842   {
843     StartReconnectionTimer();
844   }
845   else
846   {
847     mState = CONNECTED;
848   }
849
850   return connected;
851 }
852
853 void IndicatorEcoreWl::StartReconnectionTimer()
854 {
855   if( ! mReconnectTimer )
856   {
857     mReconnectTimer = Dali::Timer::New(1000);
858     mConnection.DisconnectAll();
859     mReconnectTimer.TickSignal().Connect( mConnection, &IndicatorEcoreWl::OnReconnectTimer );
860   }
861   mReconnectTimer.Start();
862 }
863
864 bool IndicatorEcoreWl::OnReconnectTimer()
865 {
866   bool retry = false;
867
868   if( mState == DISCONNECTED )
869   {
870     if( !Connect() )
871     {
872       retry = true;
873     }
874   }
875
876   return retry;
877 }
878
879 void IndicatorEcoreWl::Disconnect()
880 {
881   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
882
883   mState = DISCONNECTED;
884
885   delete mServerConnection;
886   mServerConnection = NULL;
887
888   ClearSharedFileInfo();
889 }
890
891 void IndicatorEcoreWl::Resize( int width, int height )
892 {
893   if( width < 1 )
894   {
895     width = 1;
896   }
897   if( height < 1 )
898   {
899     height = 1;
900   }
901
902   if( mImageWidth != width || mImageHeight != height )
903   {
904     mImageWidth = width;
905     mImageHeight = height;
906
907     mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
908     mIndicatorActor.SetSize( mImageWidth, mImageHeight );
909     mEventActor.SetSize(mImageWidth, mImageHeight);
910     UpdateTopMargin();
911   }
912 }
913
914 void IndicatorEcoreWl::SetLockFileInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
915 {
916   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
917
918   // epcEvent->ref == w
919   // epcEvent->ref_to == h
920   // epcEvent->response == buffer num
921   // epcEvent->data = lockfile + nul byte
922
923   if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) && (epcEvent->data) &&
924       (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
925   {
926     int n = epcEvent->response;
927
928     if( n >= 0 && n < SHARED_FILE_NUMBER )
929     {
930       mCurrentSharedFile = n;
931
932       mSharedFileInfo[n].mImageWidth  = epcEvent->ref;
933       mSharedFileInfo[n].mImageHeight = epcEvent->ref_to;
934
935       mSharedFileInfo[n].mLockFileName.clear();
936
937       mSharedFileInfo[n].mLockFileName = static_cast< char* >( epcEvent->data );
938
939       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetLockFileInfo: buffer num = %d, w = %d, h = %d, lock = %s\n",
940                      n, mSharedFileInfo[n].mImageWidth, mSharedFileInfo[n].mImageHeight, mSharedFileInfo[n].mLockFileName.c_str() );
941     }
942   }
943 }
944
945 void IndicatorEcoreWl::SetSharedImageInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
946 {
947   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
948
949   // epcEvent->ref == shm id
950   // epcEvent->ref_to == shm num
951   // epcEvent->response == buffer num
952   // epcEvent->data = shm ref string + nul byte
953
954   if ( (epcEvent->data) &&
955        (epcEvent->size > 0) &&
956        (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
957   {
958     int n = epcEvent->response;
959
960     if( n >= 0 && n < SHARED_FILE_NUMBER )
961     {
962       mCurrentSharedFile = n;
963
964       mSharedFileInfo[n].mSharedFileName.clear();
965
966       mSharedFileInfo[n].mSharedFileName = static_cast< char* >( epcEvent->data );
967
968       mSharedFileInfo[n].mSharedFileID = epcEvent->ref;
969       mSharedFileInfo[n].mSharedFileNumber = epcEvent->ref_to;
970
971       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetSharedImageInfo: buffer num %d, shared file = %s, id = %d, num = %d\n",
972                      n, mSharedFileInfo[n].mSharedFileName.c_str(), mSharedFileInfo[n].mSharedFileID, mSharedFileInfo[n].mSharedFileNumber );
973     }
974   }
975 }
976
977 void IndicatorEcoreWl::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
978 {
979   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
980
981   // epcEvent->ref == alpha
982   // epcEvent->ref_to == sys
983   // epcEvent->response == buffer num
984
985   int n = epcEvent->response;
986
987   if( n >= 0 && n < SHARED_FILE_NUMBER )
988   {
989     mCurrentSharedFile = n;
990
991     delete mSharedFileInfo[n].mSharedFile;
992     mSharedFileInfo[n].mSharedFile = NULL;
993
994     delete mSharedFileInfo[n].mLock;
995     mSharedFileInfo[n].mLock = NULL;
996
997     std::stringstream sharedFileID;
998     std::stringstream sharedFileNumber;
999
1000     sharedFileID << mSharedFileInfo[n].mSharedFileID;
1001     sharedFileNumber << mSharedFileInfo[n].mSharedFileNumber;
1002
1003     std::string sharedFilename = "/" + mSharedFileInfo[n].mSharedFileName + "-" + sharedFileID.str() + "." + sharedFileNumber.str();
1004
1005     DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "LoadSharedImage: file name = %s\n", sharedFilename.c_str() );
1006
1007     mSharedFileInfo[n].mSharedFile = SharedFile::New( sharedFilename.c_str(), mSharedFileInfo[n].mImageWidth * mSharedFileInfo[n].mImageWidth * 4, true );
1008     if( mSharedFileInfo[n].mSharedFile != NULL )
1009     {
1010       mSharedFileInfo[n].mLock = new IndicatorEcoreWl::LockFile( mSharedFileInfo[n].mLockFileName );
1011       if( mSharedFileInfo[n].mLock->RetrieveAndClearErrorStatus() )
1012       {
1013         DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", mSharedFileInfo[n].mLockFileName.c_str() );
1014       }
1015       else
1016       {
1017         CreateNewImage( n );
1018         UpdateVisibility();
1019       }
1020     }
1021   }
1022 }
1023
1024 void IndicatorEcoreWl::UpdateTopMargin()
1025 {
1026   int newMargin = (mVisible == Dali::Window::VISIBLE && mOpacityMode == Dali::Window::OPAQUE) ? mImageHeight : 0;
1027   if (mTopMargin != newMargin)
1028   {
1029     mTopMargin = newMargin;
1030     mAdaptor->IndicatorSizeChanged( mTopMargin );
1031   }
1032 }
1033
1034 void IndicatorEcoreWl::UpdateVisibility()
1035 {
1036   if( CheckVisibleState() )
1037   {
1038     // set default indicator type (enable the quick panel)
1039     OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
1040   }
1041   else
1042   {
1043     // set default indicator type (disable the quick panel)
1044     OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
1045   }
1046
1047   if( !mIsShowing )
1048   {
1049     mIndicatorContentActor.SetPosition( 0.0f, -mImageHeight, 0.0f );
1050   }
1051
1052   SetVisible(mVisible, true);
1053 }
1054
1055 void IndicatorEcoreWl::UpdateImageData( int bufferNumber )
1056 {
1057   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s  mVisible: %s", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
1058
1059   if( mState == CONNECTED && mVisible )
1060   {
1061     // not sure we can skip it when mIsShowing is false
1062     CopyToBuffer( bufferNumber );
1063   }
1064 }
1065
1066 bool IndicatorEcoreWl::CopyToBuffer( int bufferNumber )
1067 {
1068   bool success = false;
1069
1070   if( mSharedFileInfo[bufferNumber].mLock )
1071   {
1072     IndicatorEcoreWl::ScopedLock scopedLock(mSharedFileInfo[bufferNumber].mLock);
1073     if( mSharedFileInfo[bufferNumber].mLock->RetrieveAndClearErrorStatus() )
1074     {
1075       // Do nothing here.
1076     }
1077     else if( scopedLock.IsLocked() )
1078     {
1079       unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
1080       size_t size = static_cast< size_t >( mSharedFileInfo[bufferNumber].mImageWidth ) * mSharedFileInfo[bufferNumber].mImageHeight * 4;
1081
1082       if( mIndicatorBuffer->UpdatePixels( src, size ) )
1083       {
1084         mAdaptor->RequestUpdateOnce();
1085         success = true;
1086       }
1087     }
1088   }
1089
1090   return success;
1091 }
1092
1093 void IndicatorEcoreWl::CreateNewImage( int bufferNumber )
1094 {
1095   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight );
1096   mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight, Pixel::BGRA8888 );
1097   bool success = false;
1098
1099   if( CopyToBuffer( bufferNumber ) ) // Only create images if we have valid image buffer
1100   {
1101     Dali::Texture texture = Dali::Texture::New( mIndicatorBuffer->GetNativeImage() );
1102     if( texture )
1103     {
1104       SetForegroundImage( texture );
1105       success = true;
1106     }
1107   }
1108
1109   if( !success )
1110   {
1111     DALI_LOG_WARNING("### Cannot create indicator image ###\n");
1112   }
1113 }
1114
1115 Dali::Geometry IndicatorEcoreWl::CreateBackgroundGeometry()
1116 {
1117   switch( mOpacityMode )
1118   {
1119     case Dali::Window::TRANSLUCENT:
1120       if( !mTranslucentGeometry )
1121       {
1122         // Construct 5 interval mesh
1123         // 0  +---+  1
1124         //    | \ |
1125         // 2  +---+  3
1126         //    | \ |
1127         // 4  +---+  5
1128         //    | \ |
1129         // 6  +---+  7
1130         //    | \ |
1131         // 8  +---+  9
1132         //    | \ |
1133         // 10 +---+  11
1134
1135         // Create vertices
1136         struct BackgroundVertex
1137         {
1138           Vector2 mPosition;
1139           float   mAlpha;
1140         };
1141
1142         unsigned int numVertices = 2 * ( NUM_GRADIENT_INTERVALS + 1 );
1143         BackgroundVertex vertices[ numVertices ];
1144
1145         float d = -0.5f;
1146         float delta = 1.0f / NUM_GRADIENT_INTERVALS;
1147         BackgroundVertex* currentVertex = vertices;
1148         for( int y = 0; y < NUM_GRADIENT_INTERVALS + 1; ++y, d += delta )
1149         {
1150           currentVertex->mPosition = Vector2( -0.5f, d );
1151           currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1152           currentVertex++;
1153
1154           currentVertex->mPosition = Vector2( 0.5f, d );
1155           currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1156           currentVertex++;
1157         }
1158
1159         // Create indices
1160         unsigned int numIndices = 2 * 3 * NUM_GRADIENT_INTERVALS;
1161         unsigned short indices[ numIndices ];
1162
1163         unsigned short* currentIndex = indices;
1164         for( int y = 0; y < NUM_GRADIENT_INTERVALS; ++y )
1165         {
1166           *currentIndex++ = (2 * y);
1167           *currentIndex++ = (2 * y) + 3;
1168           *currentIndex++ = (2 * y) + 1;
1169
1170           *currentIndex++ = (2 * y);
1171           *currentIndex++ = (2 * y) + 2;
1172           *currentIndex++ = (2 * y) + 3;
1173         }
1174
1175         Dali::Property::Map vertexFormat;
1176         vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1177         vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1178         Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1179         vertexPropertyBuffer.SetData( vertices, numVertices );
1180
1181         // Create the geometry object
1182         mTranslucentGeometry = Dali::Geometry::New();
1183         mTranslucentGeometry.AddVertexBuffer( vertexPropertyBuffer );
1184         mTranslucentGeometry.SetIndexBuffer( &indices[0], numIndices );
1185       }
1186
1187       return mTranslucentGeometry;
1188     case Dali::Window::OPAQUE:
1189
1190       if( !mSolidGeometry )
1191       {
1192         // Create vertices
1193         struct BackgroundVertex
1194         {
1195           Vector2 mPosition;
1196           float   mAlpha;
1197         };
1198
1199         BackgroundVertex vertices[ 4 ] = { { Vector2( -0.5f, -0.5f ), 1.0f }, { Vector2( 0.5f, -0.5f ), 1.0f },
1200                                            { Vector2( -0.5f,  0.5f ), 1.0f }, { Vector2( 0.5f,  0.5f ), 1.0f } };
1201
1202         // Create indices
1203         unsigned short indices[ 6 ] = { 0, 3, 1, 0, 2, 3 };
1204
1205         Dali::Property::Map vertexFormat;
1206         vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1207         vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1208         Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1209         vertexPropertyBuffer.SetData( vertices, 4 );
1210
1211
1212         // Create the geometry object
1213         mSolidGeometry = Dali::Geometry::New();
1214         mSolidGeometry.AddVertexBuffer( vertexPropertyBuffer );
1215         mSolidGeometry.SetIndexBuffer( &indices[0], 6 );
1216       }
1217
1218       return mSolidGeometry;
1219     case Dali::Window::TRANSPARENT:
1220       break;
1221   }
1222
1223   return Dali::Geometry();
1224 }
1225
1226 void IndicatorEcoreWl::SetForegroundImage( Dali::Texture texture )
1227 {
1228   if( !mForegroundRenderer && texture )
1229   {
1230     // Create Shader
1231     Dali::Shader shader = Dali::Shader::New( FOREGROUND_VERTEX_SHADER, FOREGROUND_FRAGMENT_SHADER );
1232
1233     // Create renderer from geometry and material
1234     Dali::Geometry quad = CreateQuadGeometry();
1235     mForegroundRenderer = Dali::Renderer::New( quad, shader );
1236     // Make sure the foreground stays in front of the background
1237     mForegroundRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, 1.f );
1238
1239     // Set blend function
1240     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_RGB,    Dali::BlendFactor::ONE );
1241     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_RGB,   Dali::BlendFactor::ONE_MINUS_SRC_ALPHA );
1242     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_ALPHA,  Dali::BlendFactor::ONE );
1243     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_ALPHA, Dali::BlendFactor::ONE );
1244
1245     // Create a texture-set and add to renderer
1246
1247     Dali::TextureSet textureSet = Dali::TextureSet::New();
1248     textureSet.SetTexture( 0u, texture );
1249     mForegroundRenderer.SetTextures( textureSet );
1250
1251     mIndicatorContentActor.AddRenderer( mForegroundRenderer );
1252   }
1253   else if( mForegroundRenderer )
1254   {
1255     Dali::TextureSet textureSet = mForegroundRenderer.GetTextures();
1256     textureSet.SetTexture( 0u, texture );
1257   }
1258
1259   if( mImageWidth == 0 && mImageHeight == 0  && texture)
1260   {
1261     Resize( texture.GetWidth(), texture.GetHeight() );
1262   }
1263 }
1264
1265 void IndicatorEcoreWl::OnIndicatorTypeChanged( Type indicatorType )
1266 {
1267   if( mObserver != NULL )
1268   {
1269     mObserver->IndicatorTypeChanged( indicatorType );
1270   }
1271 }
1272
1273 void IndicatorEcoreWl::DataReceived( void* event )
1274 {
1275   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1276   Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1277
1278   switch( epcEvent->minor )
1279   {
1280     case OP_UPDATE:
1281     {
1282       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1283       if( mIsShowing )
1284       {
1285         mAdaptor->RequestUpdateOnce();
1286       }
1287       break;
1288     }
1289     case OP_UPDATE_DONE:
1290     {
1291       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
1292       // epcEvent->response == display buffer #
1293       UpdateImageData( epcEvent->response );
1294       break;
1295     }
1296     case OP_SHM_REF0:
1297     {
1298       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF0\n" );
1299       SetSharedImageInfo( epcEvent );
1300       break;
1301     }
1302     case OP_SHM_REF1:
1303     {
1304       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF1\n" );
1305       SetLockFileInfo( epcEvent );
1306       break;
1307     }
1308     case OP_SHM_REF2:
1309     {
1310       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF2\n" );
1311       LoadSharedImage( epcEvent );
1312       break;
1313     }
1314     case OP_RESIZE:
1315     {
1316       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1317
1318       if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1319       {
1320         IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1321         Resize( newSize->w, newSize->h );
1322       }
1323       break;
1324     }
1325     case OP_MSG_PARENT:
1326     {
1327       int msgDomain = epcEvent->ref;
1328       int msgId = epcEvent->ref_to;
1329
1330       void *msgData = NULL;
1331       int msgDataSize = 0;
1332       msgData = epcEvent->data;
1333       msgDataSize = epcEvent->size;
1334
1335       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT. msgDomain = %d\n", msgDomain );
1336
1337       if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1338       {
1339         switch( msgId )
1340         {
1341           case MSG_ID_INDICATOR_TYPE:
1342           {
1343             DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1344             Type* indicatorType = static_cast<Type*>( epcEvent->data );
1345             OnIndicatorTypeChanged( *indicatorType );
1346             break;
1347           }
1348
1349           case MSG_ID_INDICATOR_START_ANIMATION:
1350           {
1351             DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: MSG_ID_INDICATOR_START_ANIMATION\n" );
1352
1353             if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1354             {
1355               DALI_LOG_ERROR("Message data is incorrect\n");
1356               break;
1357             }
1358
1359             IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1360
1361             if(!CheckVisibleState())
1362             {
1363               ShowIndicator( animData->duration /* n sec */ );
1364             }
1365             break;
1366           }
1367         }
1368       }
1369       break;
1370     }
1371   }
1372 }
1373
1374 void IndicatorEcoreWl::ConnectionClosed()
1375 {
1376   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1377
1378   // Will get this callback if the server connection failed to start up.
1379   delete mServerConnection;
1380   mServerConnection = NULL;
1381   mState = DISCONNECTED;
1382
1383   // Attempt to re-connect
1384   Connect();
1385 }
1386
1387 bool IndicatorEcoreWl::CheckVisibleState()
1388 {
1389   if( mOrientation == Dali::Window::LANDSCAPE
1390     || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1391     || (mVisible == Dali::Window::INVISIBLE)
1392     || (mVisible == Dali::Window::AUTO && !mIsShowing) )
1393   {
1394     return false;
1395   }
1396
1397   return true;
1398 }
1399
1400 void IndicatorEcoreWl::ClearSharedFileInfo()
1401 {
1402   for( int i = 0; i < SHARED_FILE_NUMBER; i++ )
1403   {
1404     delete mSharedFileInfo[i].mLock;
1405     mSharedFileInfo[i].mLock = NULL;
1406
1407     delete mSharedFileInfo[i].mSharedFile;
1408     mSharedFileInfo[i].mSharedFile = NULL;
1409
1410     mSharedFileInfo[i].mLockFileName.clear();
1411     mSharedFileInfo[i].mSharedFileName.clear();
1412   }
1413 }
1414
1415 /**
1416  * duration can be this
1417  *
1418  * enum
1419  * {
1420  *  KEEP_SHOWING = -1,
1421  *  HIDE_NOW = 0
1422  * };
1423  */
1424 void IndicatorEcoreWl::ShowIndicator(float duration)
1425 {
1426   if( !mIndicatorAnimation )
1427   {
1428     mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1429     mIndicatorAnimation.FinishedSignal().Connect(this, &IndicatorEcoreWl::OnAnimationFinished);
1430   }
1431
1432   if(mIsShowing && !EqualsZero(duration))
1433   {
1434     // If need to show during showing, do nothing.
1435     // In 2nd phase (below) will update timer
1436   }
1437   else if(!mIsShowing && mIsAnimationPlaying && EqualsZero(duration))
1438   {
1439     // If need to hide during hiding or hidden already, do nothing
1440   }
1441   else
1442   {
1443     mIndicatorAnimation.Clear();
1444
1445     if( EqualsZero(duration) )
1446     {
1447       mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, -mImageHeight, 0), Dali::AlphaFunction::EASE_OUT );
1448
1449       mIsShowing = false;
1450
1451       OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1452     }
1453     else
1454     {
1455       mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, 0, 0), Dali::AlphaFunction::EASE_OUT );
1456
1457       mIsShowing = true;
1458
1459       OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1460     }
1461
1462     mIndicatorAnimation.Play();
1463     mIsAnimationPlaying = true;
1464   }
1465
1466   if(duration > 0)
1467   {
1468     if(!mShowTimer)
1469     {
1470       mShowTimer = Dali::Timer::New(1000 * duration);
1471       mShowTimer.TickSignal().Connect(this, &IndicatorEcoreWl::OnShowTimer);
1472     }
1473     mShowTimer.SetInterval(1000* duration);
1474     mShowTimer.Start();
1475
1476     if( mVisible == Dali::Window::AUTO )
1477     {
1478       // check the stage touch
1479       Dali::Stage::GetCurrent().TouchSignal().Connect( this, &IndicatorEcoreWl::OnStageTouch );
1480     }
1481   }
1482   else
1483   {
1484     if(mShowTimer && mShowTimer.IsRunning())
1485     {
1486       mShowTimer.Stop();
1487     }
1488
1489     if( mVisible == Dali::Window::AUTO )
1490     {
1491       // check the stage touch
1492       Dali::Stage::GetCurrent().TouchSignal().Disconnect( this, &IndicatorEcoreWl::OnStageTouch );
1493     }
1494   }
1495 }
1496
1497 bool IndicatorEcoreWl::OnShowTimer()
1498 {
1499   // after time up, hide indicator
1500   ShowIndicator( HIDE_NOW );
1501
1502   return false;
1503 }
1504
1505 void IndicatorEcoreWl::OnAnimationFinished(Dali::Animation& animation)
1506 {
1507   mIsAnimationPlaying = false;
1508   // once animation is finished and indicator is hidden, take it off stage
1509   if( mObserver != NULL )
1510   {
1511     mObserver->IndicatorVisibilityChanged( mIsShowing ); // is showing?
1512   }
1513 }
1514
1515 void IndicatorEcoreWl::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
1516 {
1517   // Nothing to do, but we still want to consume pan
1518 }
1519
1520 void IndicatorEcoreWl::OnStageTouch(const Dali::TouchData& touchData)
1521 {
1522   // when stage is touched while indicator is showing temporary, hide it
1523   if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1524   {
1525     switch( touchData.GetState(0) )
1526     {
1527       case Dali::PointState::DOWN:
1528       {
1529         // if touch point is inside the indicator, indicator is not hidden
1530         if( mImageHeight < int( touchData.GetScreenPosition(0).y ) )
1531         {
1532           ShowIndicator( HIDE_NOW );
1533         }
1534         break;
1535       }
1536
1537       default:
1538       break;
1539     }
1540   }
1541 }
1542
1543 } // Adaptor
1544
1545 } // Internal
1546
1547 } // Dali
1548
1549 #pragma GCC diagnostic pop