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