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