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