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