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