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