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