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