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