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