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