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