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