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