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