[3.0] Fix crash by Indicator lock file 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/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   mTopMargin( 0 )
506 {
507   mIndicatorContentActor = Dali::Actor::New();
508   mIndicatorContentActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
509   mIndicatorContentActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
510
511   // Indicator image handles the touch event including "leave"
512   mIndicatorContentActor.SetLeaveRequired( true );
513   mIndicatorContentActor.TouchedSignal().Connect( this, &Indicator::OnTouched );
514   mIndicatorContentActor.SetColor( Color::BLACK );
515
516   mIndicatorActor = Dali::Actor::New();
517   mIndicatorActor.Add( mIndicatorContentActor );
518
519   // Event handler to find out flick down gesture
520   mEventActor = Dali::Actor::New();
521   mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
522   mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
523   mIndicatorActor.Add( mEventActor );
524
525   // Attach pan gesture to find flick down during hiding.
526   // It can prevent the problem that scrollview gets pan gesture even indicator area is touched,
527   // since it consumes the pan gesture in advance.
528   mPanDetector = Dali::PanGestureDetector::New();
529   mPanDetector.DetectedSignal().Connect( this, &Indicator::OnPan );
530   mPanDetector.Attach( mEventActor );
531
532   Open( orientation );
533
534   // register indicator to accessibility adaptor
535   Dali::AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
536   if(accessibilityAdaptor)
537   {
538     AccessibilityAdaptor::GetImplementation( accessibilityAdaptor ).SetIndicator( this );
539   }
540   // hide the indicator by default
541   mIndicatorActor.SetVisible( false );
542
543   // create impl to handle ecore event
544   mImpl = new Impl(this);
545 }
546
547 Indicator::~Indicator()
548 {
549   if(mImpl)
550   {
551     delete mImpl;
552     mImpl = NULL;
553   }
554
555   if(mEventActor)
556   {
557     mEventActor.TouchedSignal().Disconnect( this, &Indicator::OnTouched );
558   }
559   Disconnect();
560 }
561
562 void Indicator::SetAdaptor(Adaptor* adaptor)
563 {
564   mAdaptor = adaptor;
565   mIndicatorBuffer->SetAdaptor( adaptor );
566 }
567
568 Dali::Actor Indicator::GetActor()
569 {
570   return mIndicatorActor;
571 }
572
573 void Indicator::Open( Dali::Window::WindowOrientation orientation )
574 {
575   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
576
577   // Calls from Window should be set up to ensure we are in a
578   // disconnected state before opening a second time.
579   DALI_ASSERT_DEBUG( mState == DISCONNECTED );
580
581   mOrientation = orientation;
582
583   Connect();
584
585   // Change background visibility depending on orientation
586   if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE  )
587   {
588     if( mBackgroundRenderer )
589     {
590       mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
591       mBackgroundVisible = false;
592     }
593   }
594   else
595   {
596     SetOpacityMode( mOpacityMode );
597   }
598 }
599
600 void Indicator::Close()
601 {
602   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s", STATE_DEBUG_STRING(mState) );
603
604   if( mState == CONNECTED )
605   {
606     Disconnect();
607     if( mObserver != NULL )
608     {
609       mObserver->IndicatorClosed( this );
610     }
611   }
612
613   Dali::Texture emptyTexture;
614   SetForegroundImage( emptyTexture );
615 }
616
617 void Indicator::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
618 {
619   mOpacityMode = mode;
620
621   Dali::Geometry geometry = CreateBackgroundGeometry();
622   if( geometry )
623   {
624     if( mBackgroundRenderer )
625     {
626       if( mBackgroundRenderer.GetGeometry() != geometry )
627       {
628         mBackgroundRenderer.SetGeometry( geometry );
629       }
630     }
631     else
632     {
633       if( !mBackgroundShader )
634       {
635         mBackgroundShader = Dali::Shader::New( BACKGROUND_VERTEX_SHADER, BACKGROUND_FRAGMENT_SHADER, Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT );
636       }
637
638       mBackgroundRenderer = Dali::Renderer::New( geometry, mBackgroundShader );
639     }
640
641     if( !mBackgroundVisible )
642     {
643       mIndicatorContentActor.AddRenderer( mBackgroundRenderer );
644       mBackgroundVisible = true;
645     }
646   }
647   else if( mBackgroundRenderer )
648   {
649     mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
650     mBackgroundVisible = false;
651   }
652   UpdateTopMargin();
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     UpdateTopMargin();
684
685     if( mForegroundRenderer && mForegroundRenderer.GetTextures().GetTexture( 0u ) )
686     {
687       if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
688       {
689         // hide indicator
690         ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
691       }
692       else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
693       {
694         // show indicator
695         ShowIndicator( KEEP_SHOWING );
696       }
697       else
698       {
699         // hide indicator
700         ShowIndicator( HIDE_NOW );
701       }
702     }
703     else
704     {
705       mIsShowing = false;
706     }
707   }
708 }
709
710 bool Indicator::IsConnected()
711 {
712   return ( mState == CONNECTED );
713 }
714
715 bool Indicator::SendMessage( int messageDomain, int messageId, const void *data, int size )
716 {
717  if(IsConnected())
718  {
719    return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
720  }
721  else
722  {
723    return false;
724  }
725 }
726
727 bool Indicator::OnTouched(Dali::Actor indicator, const Dali::TouchEvent& touchEvent)
728 {
729   if( mServerConnection )
730   {
731     const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
732
733     // Send touch event to indicator server when indicator is showing
734     if( CheckVisibleState() || mIsShowing )
735     {
736       switch( touchPoint.state )
737       {
738         case Dali::PointState::DOWN:
739         {
740           IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
741           IpcDataEvMouseDown ipcDown( touchEvent.time );
742           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
743           mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
744
745           if( mVisible == Dali::Window::AUTO )
746           {
747             // Stop hiding indicator
748             ShowIndicator( KEEP_SHOWING );
749           }
750         }
751         break;
752
753         case Dali::PointState::MOTION:
754         {
755           IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
756           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
757         }
758         break;
759
760         case Dali::PointState::UP:
761         case Dali::PointState::INTERRUPTED:
762         {
763           IpcDataEvMouseUp ipcUp( touchEvent.time );
764           mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
765
766           if( mVisible == Dali::Window::AUTO )
767           {
768             // Hide indicator
769             ShowIndicator( 0.5f /* hide after 0.5 sec */ );
770           }
771         }
772         break;
773
774         case Dali::TouchPoint::Leave:
775         {
776           IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
777           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
778           IpcDataEvMouseUp ipcOut( touchEvent.time );
779           mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
780         }
781         break;
782
783         default:
784           break;
785       }
786
787       return true;
788     }
789   }
790
791   return false;
792 }
793
794 bool Indicator::Connect()
795 {
796   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
797
798   DALI_ASSERT_DEBUG( mState == DISCONNECTED );
799
800   bool connected = false;
801
802   mServerConnection = new ServerConnection( INDICATOR_SERVICE_NAME, 0, false, this );
803   if( mServerConnection )
804   {
805     connected = mServerConnection->IsConnected();
806     if( ! connected )
807     {
808       delete mServerConnection;
809       mServerConnection = NULL;
810     }
811   }
812
813   if( !connected )
814   {
815     StartReconnectionTimer();
816   }
817   else
818   {
819     mState = CONNECTED;
820   }
821
822   return connected;
823 }
824
825 void Indicator::StartReconnectionTimer()
826 {
827   if( ! mReconnectTimer )
828   {
829     mReconnectTimer = Dali::Timer::New(1000);
830     mConnection.DisconnectAll();
831     mReconnectTimer.TickSignal().Connect( mConnection, &Indicator::OnReconnectTimer );
832   }
833   mReconnectTimer.Start();
834 }
835
836 bool Indicator::OnReconnectTimer()
837 {
838   bool retry = false;
839
840   if( mState == DISCONNECTED )
841   {
842     if( !Connect() )
843     {
844       retry = true;
845     }
846   }
847
848   return retry;
849 }
850
851 void Indicator::Disconnect()
852 {
853   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
854
855   mState = DISCONNECTED;
856
857   delete mServerConnection;
858   mServerConnection = NULL;
859
860   ClearSharedFileInfo();
861 }
862
863 void Indicator::Resize( int width, int height )
864 {
865   if( width < 1 )
866   {
867     width = 1;
868   }
869   if( height < 1 )
870   {
871     height = 1;
872   }
873
874   if( mImageWidth != width || mImageHeight != height )
875   {
876     mImageWidth = width;
877     mImageHeight = height;
878
879     mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
880     mIndicatorActor.SetSize( mImageWidth, mImageHeight );
881     mEventActor.SetSize(mImageWidth, mImageHeight);
882     UpdateTopMargin();
883   }
884 }
885
886 void Indicator::SetLockFileInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
887 {
888   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
889
890   // epcEvent->ref == w
891   // epcEvent->ref_to == h
892   // epcEvent->response == buffer num
893   // epcEvent->data = lockfile + nul byte
894
895   if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) && (epcEvent->data) &&
896       (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
897   {
898     int n = epcEvent->response;
899
900     if( n >= 0 && n < SHARED_FILE_NUMBER )
901     {
902       mCurrentSharedFile = n;
903
904       mSharedFileInfo[n].mImageWidth  = epcEvent->ref;
905       mSharedFileInfo[n].mImageHeight = epcEvent->ref_to;
906
907       mSharedFileInfo[n].mLockFileName.clear();
908
909       mSharedFileInfo[n].mLockFileName = static_cast< char* >( epcEvent->data );
910
911       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetLockFileInfo: buffer num = %d, w = %d, h = %d, lock = %s\n",
912                      n, mSharedFileInfo[n].mImageWidth, mSharedFileInfo[n].mImageHeight, mSharedFileInfo[n].mLockFileName.c_str() );
913     }
914   }
915 }
916
917 void Indicator::SetSharedImageInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
918 {
919   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
920
921   // epcEvent->ref == shm id
922   // epcEvent->ref_to == shm num
923   // epcEvent->response == buffer num
924   // epcEvent->data = shm ref string + nul byte
925
926   if ( (epcEvent->data) &&
927        (epcEvent->size > 0) &&
928        (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
929   {
930     int n = epcEvent->response;
931
932     if( n >= 0 && n < SHARED_FILE_NUMBER )
933     {
934       mCurrentSharedFile = n;
935
936       mSharedFileInfo[n].mSharedFileName.clear();
937
938       mSharedFileInfo[n].mSharedFileName = static_cast< char* >( epcEvent->data );
939
940       mSharedFileInfo[n].mSharedFileID = epcEvent->ref;
941       mSharedFileInfo[n].mSharedFileNumber = epcEvent->ref_to;
942
943       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetSharedImageInfo: buffer num %d, shared file = %s, id = %d, num = %d\n",
944                      n, mSharedFileInfo[n].mSharedFileName.c_str(), mSharedFileInfo[n].mSharedFileID, mSharedFileInfo[n].mSharedFileNumber );
945     }
946   }
947 }
948
949 void Indicator::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
950 {
951   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
952
953   // epcEvent->ref == alpha
954   // epcEvent->ref_to == sys
955   // epcEvent->response == buffer num
956
957   if ( mSharedBufferType != BUFFER_TYPE_SHM )
958   {
959     return ;
960   }
961
962   int n = epcEvent->response;
963
964   if( n >= 0 && n < SHARED_FILE_NUMBER )
965   {
966     mCurrentSharedFile = n;
967
968     delete mSharedFileInfo[n].mSharedFile;
969     mSharedFileInfo[n].mSharedFile = NULL;
970
971     delete mSharedFileInfo[n].mLock;
972     mSharedFileInfo[n].mLock = NULL;
973
974     std::stringstream sharedFileID;
975     std::stringstream sharedFileNumber;
976
977     sharedFileID << mSharedFileInfo[n].mSharedFileID;
978     sharedFileNumber << mSharedFileInfo[n].mSharedFileNumber;
979
980     std::string sharedFilename = "/" + mSharedFileInfo[n].mSharedFileName + "-" + sharedFileID.str() + "." + sharedFileNumber.str();
981
982     DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "LoadSharedImage: file name = %s\n", sharedFilename.c_str() );
983
984     mSharedFileInfo[n].mSharedFile = SharedFile::New( sharedFilename.c_str(), mSharedFileInfo[n].mImageWidth * mSharedFileInfo[n].mImageWidth * 4, true );
985     if( mSharedFileInfo[n].mSharedFile != NULL )
986     {
987       mSharedFileInfo[n].mLock = new Indicator::LockFile( mSharedFileInfo[n].mLockFileName );
988       if( mSharedFileInfo[n].mLock->RetrieveAndClearErrorStatus() )
989       {
990         DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", mSharedFileInfo[n].mLockFileName.c_str() );
991
992         return;
993       }
994
995       CreateNewImage( n );
996       UpdateVisibility();
997     }
998   }
999 }
1000
1001 void Indicator::LoadPixmapImage( Ecore_Ipc_Event_Server_Data *epcEvent )
1002 {
1003   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1004
1005   // epcEvent->ref == pixmap id
1006   // epcEvent->ref_to == type
1007   // epcEvent->response == buffer num
1008
1009   if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
1010   {
1011     mSharedBufferType = (BufferType)(epcEvent->ref_to);
1012
1013     ClearSharedFileInfo();
1014
1015     mPixmap = static_cast<PixmapId>(epcEvent->ref);
1016     DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "mPixmap [%x]", mPixmap);
1017
1018     CreateNewPixmapImage();
1019     UpdateVisibility();
1020   }
1021 }
1022
1023 void Indicator::UpdateTopMargin()
1024 {
1025   int newMargin = (mVisible == Dali::Window::VISIBLE && mOpacityMode == Dali::Window::OPAQUE) ? mImageHeight : 0;
1026   if (mTopMargin != newMargin)
1027   {
1028     mTopMargin = newMargin;
1029     mAdaptor->IndicatorSizeChanged( mTopMargin );
1030   }
1031 }
1032
1033 void Indicator::UpdateVisibility()
1034 {
1035   if( CheckVisibleState() )
1036   {
1037     // set default indicator type (enable the quick panel)
1038     OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
1039   }
1040   else
1041   {
1042     // set default indicator type (disable the quick panel)
1043     OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
1044   }
1045
1046   if( !mIsShowing )
1047   {
1048     mIndicatorContentActor.SetPosition( 0.0f, -mImageHeight, 0.0f );
1049   }
1050
1051   SetVisible(mVisible, true);
1052 }
1053
1054 void Indicator::UpdateImageData( int bufferNumber )
1055 {
1056   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s  mVisible: %s", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
1057
1058   if( mState == CONNECTED && mVisible )
1059   {
1060     if(mPixmap == 0)
1061     {
1062       // in case of shm indicator (not pixmap), not sure we can skip it when mIsShowing is false
1063       CopyToBuffer( bufferNumber );
1064     }
1065     else
1066     {
1067       if(mIsShowing)
1068       {
1069         mAdaptor->RequestUpdateOnce();
1070       }
1071     }
1072   }
1073 }
1074
1075 bool Indicator::CopyToBuffer( int bufferNumber )
1076 {
1077   bool success = false;
1078
1079   if( mSharedFileInfo[bufferNumber].mLock )
1080   {
1081     Indicator::ScopedLock scopedLock(mSharedFileInfo[bufferNumber].mLock);
1082     if( mSharedFileInfo[bufferNumber].mLock->RetrieveAndClearErrorStatus() )
1083     {
1084       // Do nothing here.
1085     }
1086     else if( scopedLock.IsLocked() )
1087     {
1088       unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
1089       size_t size = mSharedFileInfo[bufferNumber].mImageWidth * mSharedFileInfo[bufferNumber].mImageHeight * 4;
1090
1091       if( mIndicatorBuffer->UpdatePixels( src, size ) )
1092       {
1093         mAdaptor->RequestUpdateOnce();
1094         success = true;
1095       }
1096     }
1097   }
1098
1099   return success;
1100 }
1101
1102 void Indicator::CreateNewPixmapImage()
1103 {
1104   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mImageWidth, mImageHeight );
1105   Dali::NativeImageSourcePtr nativeImageSource = Dali::NativeImageSource::New( mPixmap );
1106
1107   if( nativeImageSource )
1108   {
1109     Dali::Texture texture = Dali::Texture::New( *nativeImageSource );
1110     SetForegroundImage( texture );
1111     mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
1112     mIndicatorActor.SetSize( mImageWidth, mImageHeight );
1113     mEventActor.SetSize( mImageWidth, mImageHeight );
1114     UpdateTopMargin();
1115   }
1116   else
1117   {
1118     DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
1119     Disconnect();
1120     if( mObserver != NULL )
1121     {
1122       mObserver->IndicatorClosed( this );
1123     }
1124     // Don't do connection in this callback - strange things happen!
1125     StartReconnectionTimer();
1126   }
1127 }
1128
1129 void Indicator::CreateNewImage( int bufferNumber )
1130 {
1131   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight );
1132   mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight, Pixel::BGRA8888 );
1133   bool success = false;
1134
1135   if( CopyToBuffer( bufferNumber ) ) // Only create images if we have valid image buffer
1136   {
1137     Dali::Texture texture = Dali::Texture::New( mIndicatorBuffer->GetNativeImage() );
1138     if( texture )
1139     {
1140       SetForegroundImage( texture );
1141       success = true;
1142     }
1143   }
1144
1145   if( !success )
1146   {
1147     DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
1148     Disconnect();
1149     if( mObserver != NULL )
1150     {
1151       mObserver->IndicatorClosed( this );
1152     }
1153     // Don't do connection in this callback - strange things happen!
1154     StartReconnectionTimer();
1155   }
1156 }
1157
1158 Dali::Geometry Indicator::CreateBackgroundGeometry()
1159 {
1160   switch( mOpacityMode )
1161   {
1162     case Dali::Window::TRANSLUCENT:
1163       if( !mTranslucentGeometry )
1164       {
1165         // Construct 5 interval mesh
1166         // 0  +---+  1
1167         //    | \ |
1168         // 2  +---+  3
1169         //    | \ |
1170         // 4  +---+  5
1171         //    | \ |
1172         // 6  +---+  7
1173         //    | \ |
1174         // 8  +---+  9
1175         //    | \ |
1176         // 10 +---+  11
1177
1178         // Create vertices
1179         struct BackgroundVertex
1180         {
1181           Vector2 mPosition;
1182           float   mAlpha;
1183         };
1184
1185         unsigned int numVertices = 2 * ( NUM_GRADIENT_INTERVALS + 1 );
1186         BackgroundVertex vertices[ numVertices ];
1187
1188         float d = -0.5f;
1189         float delta = 1.0f / NUM_GRADIENT_INTERVALS;
1190         BackgroundVertex* currentVertex = vertices;
1191         for( int y = 0; y < NUM_GRADIENT_INTERVALS + 1; ++y, d += delta )
1192         {
1193           currentVertex->mPosition = Vector2( -0.5f, d );
1194           currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1195           currentVertex++;
1196
1197           currentVertex->mPosition = Vector2( 0.5f, d );
1198           currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1199           currentVertex++;
1200         }
1201
1202         // Create indices
1203         unsigned int numIndices = 2 * 3 * NUM_GRADIENT_INTERVALS;
1204         unsigned short indices[ numIndices ];
1205
1206         unsigned short* currentIndex = indices;
1207         for( int y = 0; y < NUM_GRADIENT_INTERVALS; ++y )
1208         {
1209           *currentIndex++ = (2 * y);
1210           *currentIndex++ = (2 * y) + 3;
1211           *currentIndex++ = (2 * y) + 1;
1212
1213           *currentIndex++ = (2 * y);
1214           *currentIndex++ = (2 * y) + 2;
1215           *currentIndex++ = (2 * y) + 3;
1216         }
1217
1218         Dali::Property::Map vertexFormat;
1219         vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1220         vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1221         Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1222         vertexPropertyBuffer.SetData( vertices, numVertices );
1223
1224         // Create the geometry object
1225         mTranslucentGeometry = Dali::Geometry::New();
1226         mTranslucentGeometry.AddVertexBuffer( vertexPropertyBuffer );
1227         mTranslucentGeometry.SetIndexBuffer( &indices[0], numIndices );
1228       }
1229
1230       return mTranslucentGeometry;
1231     case Dali::Window::OPAQUE:
1232
1233       if( !mSolidGeometry )
1234       {
1235         // Create vertices
1236         struct BackgroundVertex
1237         {
1238           Vector2 mPosition;
1239           float   mAlpha;
1240         };
1241
1242         BackgroundVertex vertices[ 4 ] = { { Vector2( -0.5f, -0.5f ), 1.0f }, { Vector2( 0.5f, -0.5f ), 1.0f },
1243                                            { Vector2( -0.5f,  0.5f ), 1.0f }, { Vector2( 0.5f,  0.5f ), 1.0f } };
1244
1245         // Create indices
1246         unsigned short indices[ 6 ] = { 0, 3, 1, 0, 2, 3 };
1247
1248         Dali::Property::Map vertexFormat;
1249         vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1250         vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1251         Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1252         vertexPropertyBuffer.SetData( vertices, 4 );
1253
1254
1255         // Create the geometry object
1256         mSolidGeometry = Dali::Geometry::New();
1257         mSolidGeometry.AddVertexBuffer( vertexPropertyBuffer );
1258         mSolidGeometry.SetIndexBuffer( &indices[0], 6 );
1259       }
1260
1261       return mSolidGeometry;
1262     case Dali::Window::TRANSPARENT:
1263       break;
1264   }
1265
1266   return Dali::Geometry();
1267 }
1268
1269 void Indicator::SetForegroundImage( Dali::Texture texture )
1270 {
1271   if( !mForegroundRenderer && texture )
1272   {
1273     // Create Shader
1274     Dali::Shader shader = Dali::Shader::New( FOREGROUND_VERTEX_SHADER, FOREGROUND_FRAGMENT_SHADER );
1275
1276     // Create renderer from geometry and material
1277     Dali::Geometry quad = CreateQuadGeometry();
1278     mForegroundRenderer = Dali::Renderer::New( quad, shader );
1279     // Make sure the foreground stays in front of the background
1280     mForegroundRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, 1.f );
1281
1282     // Set blend function
1283     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_RGB,    Dali::BlendFactor::ONE );
1284     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_RGB,   Dali::BlendFactor::ONE_MINUS_SRC_ALPHA );
1285     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_ALPHA,  Dali::BlendFactor::ONE );
1286     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_ALPHA, Dali::BlendFactor::ONE );
1287
1288     // Create a texture-set and add to renderer
1289
1290     Dali::TextureSet textureSet = Dali::TextureSet::New();
1291     textureSet.SetTexture( 0u, texture );
1292     mForegroundRenderer.SetTextures( textureSet );
1293
1294     mIndicatorContentActor.AddRenderer( mForegroundRenderer );
1295   }
1296   else if( mForegroundRenderer )
1297   {
1298     Dali::TextureSet textureSet = mForegroundRenderer.GetTextures();
1299     textureSet.SetTexture( 0u, texture );
1300   }
1301
1302   if( mImageWidth == 0 && mImageHeight == 0  && texture)
1303   {
1304     Resize( texture.GetWidth(), texture.GetHeight() );
1305   }
1306 }
1307
1308 void Indicator::OnIndicatorTypeChanged( Type indicatorType )
1309 {
1310   if( mObserver != NULL )
1311   {
1312     mObserver->IndicatorTypeChanged( indicatorType );
1313   }
1314 }
1315
1316 void Indicator::DataReceived( void* event )
1317 {
1318   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1319   Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1320
1321   switch( epcEvent->minor )
1322   {
1323     case OP_UPDATE:
1324     {
1325       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1326       if( mIsShowing )
1327       {
1328         mAdaptor->RequestUpdateOnce();
1329       }
1330       break;
1331     }
1332     case OP_UPDATE_DONE:
1333     {
1334       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
1335       // epcEvent->response == display buffer #
1336       UpdateImageData( epcEvent->response );
1337       break;
1338     }
1339     case OP_SHM_REF0:
1340     {
1341       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF0\n" );
1342       SetSharedImageInfo( epcEvent );
1343       break;
1344     }
1345     case OP_SHM_REF1:
1346     {
1347       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF1\n" );
1348       SetLockFileInfo( epcEvent );
1349       break;
1350     }
1351     case OP_SHM_REF2:
1352     {
1353       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF2\n" );
1354       LoadSharedImage( epcEvent );
1355       break;
1356     }
1357     case OP_PIXMAP_REF:
1358     {
1359       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_PIXMAP_REF\n" );
1360       LoadPixmapImage( epcEvent );
1361       break;
1362     }
1363     case OP_RESIZE:
1364     {
1365       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1366
1367       if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1368       {
1369         IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1370         Resize( newSize->w, newSize->h );
1371       }
1372       break;
1373     }
1374     case OP_MSG_PARENT:
1375     {
1376       int msgDomain = epcEvent->ref;
1377       int msgId = epcEvent->ref_to;
1378
1379       void *msgData = NULL;
1380       int msgDataSize = 0;
1381       msgData = epcEvent->data;
1382       msgDataSize = epcEvent->size;
1383
1384       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT. msgDomain = %d\n", msgDomain );
1385
1386       if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1387       {
1388         switch( msgId )
1389         {
1390           case MSG_ID_INDICATOR_TYPE:
1391           {
1392             DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1393             Type* indicatorType = static_cast<Type*>( epcEvent->data );
1394             OnIndicatorTypeChanged( *indicatorType );
1395             break;
1396           }
1397
1398           case MSG_ID_INDICATOR_START_ANIMATION:
1399           {
1400             DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: MSG_ID_INDICATOR_START_ANIMATION\n" );
1401
1402             if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1403             {
1404               DALI_LOG_ERROR("Message data is incorrect\n");
1405               break;
1406             }
1407
1408             IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1409
1410             if(!CheckVisibleState())
1411             {
1412               ShowIndicator( animData->duration /* n sec */ );
1413             }
1414             break;
1415           }
1416         }
1417       }
1418       break;
1419     }
1420   }
1421 }
1422
1423 void Indicator::ConnectionClosed()
1424 {
1425   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1426
1427   // Will get this callback if the server connection failed to start up.
1428   delete mServerConnection;
1429   mServerConnection = NULL;
1430   mState = DISCONNECTED;
1431
1432   // Attempt to re-connect
1433   Connect();
1434 }
1435
1436 bool Indicator::CheckVisibleState()
1437 {
1438   if( mOrientation == Dali::Window::LANDSCAPE
1439     || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1440     || (mVisible == Dali::Window::INVISIBLE)
1441     || (mVisible == Dali::Window::AUTO && !mIsShowing) )
1442   {
1443     return false;
1444   }
1445
1446   return true;
1447 }
1448
1449 void Indicator::ClearSharedFileInfo()
1450 {
1451   for( int i = 0; i < SHARED_FILE_NUMBER; i++ )
1452   {
1453     delete mSharedFileInfo[i].mLock;
1454     mSharedFileInfo[i].mLock = NULL;
1455
1456     delete mSharedFileInfo[i].mSharedFile;
1457     mSharedFileInfo[i].mSharedFile = NULL;
1458
1459     mSharedFileInfo[i].mLockFileName.clear();
1460     mSharedFileInfo[i].mSharedFileName.clear();
1461   }
1462 }
1463
1464 /**
1465  * duration can be this
1466  *
1467  * enum
1468  * {
1469  *  KEEP_SHOWING = -1,
1470  *  HIDE_NOW = 0
1471  * };
1472  */
1473 void Indicator::ShowIndicator(float duration)
1474 {
1475   if( !mIndicatorAnimation )
1476   {
1477     mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1478     mIndicatorAnimation.FinishedSignal().Connect(this, &Indicator::OnAnimationFinished);
1479   }
1480
1481   if(mIsShowing && !EqualsZero(duration))
1482   {
1483     // If need to show during showing, do nothing.
1484     // In 2nd phase (below) will update timer
1485   }
1486   else if(!mIsShowing && mIsAnimationPlaying && EqualsZero(duration))
1487   {
1488     // If need to hide during hiding or hidden already, do nothing
1489   }
1490   else
1491   {
1492     mIndicatorAnimation.Clear();
1493
1494     if( EqualsZero(duration) )
1495     {
1496       mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, -mImageHeight, 0), Dali::AlphaFunction::EASE_OUT );
1497
1498       mIsShowing = false;
1499
1500       OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1501     }
1502     else
1503     {
1504       mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, 0, 0), Dali::AlphaFunction::EASE_OUT );
1505
1506       mIsShowing = true;
1507
1508       OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1509     }
1510
1511     mIndicatorAnimation.Play();
1512     mIsAnimationPlaying = true;
1513   }
1514
1515   if(duration > 0)
1516   {
1517     if(!mShowTimer)
1518     {
1519       mShowTimer = Dali::Timer::New(1000 * duration);
1520       mShowTimer.TickSignal().Connect(this, &Indicator::OnShowTimer);
1521     }
1522     mShowTimer.SetInterval(1000* duration);
1523     mShowTimer.Start();
1524
1525     if( mVisible == Dali::Window::AUTO )
1526     {
1527       // check the stage touch
1528       Dali::Stage::GetCurrent().TouchedSignal().Connect( this, &Indicator::OnStageTouched );
1529     }
1530   }
1531   else
1532   {
1533     if(mShowTimer && mShowTimer.IsRunning())
1534     {
1535       mShowTimer.Stop();
1536     }
1537
1538     if( mVisible == Dali::Window::AUTO )
1539     {
1540       // check the stage touch
1541       Dali::Stage::GetCurrent().TouchedSignal().Disconnect( this, &Indicator::OnStageTouched );
1542     }
1543   }
1544 }
1545
1546 bool Indicator::OnShowTimer()
1547 {
1548   // after time up, hide indicator
1549   ShowIndicator( HIDE_NOW );
1550
1551   return false;
1552 }
1553
1554 void Indicator::OnAnimationFinished(Dali::Animation& animation)
1555 {
1556   mIsAnimationPlaying = false;
1557   // once animation is finished and indicator is hidden, take it off stage
1558   if( mObserver != NULL )
1559   {
1560     mObserver->IndicatorVisibilityChanged( mIsShowing ); // is showing?
1561   }
1562 }
1563
1564 void Indicator::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
1565 {
1566   return ;
1567
1568   if( mServerConnection )
1569   {
1570     switch( gesture.state )
1571     {
1572       case Gesture::Started:
1573       {
1574         mGestureDetected = false;
1575
1576         // The gesture position is the current position after it has moved by the displacement.
1577         // We want to reference the original position.
1578         mGestureDeltaY = gesture.position.y - gesture.displacement.y;
1579       }
1580
1581       // No break, Fall through
1582       case Gesture::Continuing:
1583       {
1584         if( mVisible == Dali::Window::AUTO && !mIsShowing )
1585         {
1586           // Only take one touch point
1587           if( gesture.numberOfTouches == 1 && mGestureDetected == false )
1588           {
1589             mGestureDeltaY += gesture.displacement.y;
1590
1591             if( mGestureDeltaY >= mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE )
1592             {
1593               ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
1594               mGestureDetected = true;
1595             }
1596           }
1597         }
1598
1599         break;
1600       }
1601
1602       case Gesture::Finished:
1603       case Gesture::Cancelled:
1604       {
1605         // if indicator is showing, hide again when touching is finished (Since touch leave is activated, checking it in gesture::finish instead of touch::up)
1606         if( mVisible == Dali::Window::AUTO && mIsShowing )
1607         {
1608           ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
1609         }
1610         break;
1611       }
1612
1613
1614       default:
1615         break;
1616     }
1617   }
1618 }
1619
1620 void Indicator::OnStageTouched(const Dali::TouchEvent& touchEvent)
1621 {
1622   const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
1623
1624   // when stage is touched while indicator is showing temporary, hide it
1625   if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1626   {
1627     switch( touchPoint.state )
1628     {
1629       case Dali::PointState::DOWN:
1630       {
1631         // if touch point is inside the indicator, indicator is not hidden
1632         if( mImageHeight < int(touchPoint.screen.y) )
1633         {
1634           ShowIndicator( HIDE_NOW );
1635         }
1636         break;
1637       }
1638
1639       default:
1640       break;
1641     }
1642   }
1643 }
1644
1645 } // Adaptor
1646 } // Internal
1647 } // Dali