Revert "[Tizen] Revert "Support multiple window rendering""
[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 {
449   mIndicatorContentActor = Dali::Actor::New();
450   mIndicatorContentActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
451   mIndicatorContentActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
452
453   // Indicator image handles the touch event including "leave"
454   mIndicatorContentActor.SetLeaveRequired( true );
455   mIndicatorContentActor.TouchSignal().Connect( this, &IndicatorEcoreWl::OnTouch );
456   mIndicatorContentActor.SetColor( Color::BLACK );
457
458   mIndicatorActor = Dali::Actor::New();
459   mIndicatorActor.Add( mIndicatorContentActor );
460
461   // Event handler to find out flick down gesture
462   mEventActor = Dali::Actor::New();
463   mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
464   mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
465   mIndicatorActor.Add( mEventActor );
466
467   // Attach pan gesture to find flick down during hiding.
468   // It can prevent the problem that scrollview gets pan gesture even indicator area is touched,
469   // since it consumes the pan gesture in advance.
470   mPanDetector = Dali::PanGestureDetector::New();
471   mPanDetector.DetectedSignal().Connect( this, &IndicatorEcoreWl::OnPan );
472   mPanDetector.Attach( mEventActor );
473
474   Open( orientation );
475
476   // register indicator to accessibility adaptor
477   Dali::AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
478   if(accessibilityAdaptor)
479   {
480     AccessibilityAdaptor::GetImplementation( accessibilityAdaptor ).SetIndicator( this );
481   }
482   // hide the indicator by default
483   mIndicatorActor.SetVisible( false );
484 }
485
486 IndicatorEcoreWl::~IndicatorEcoreWl()
487 {
488   if(mEventActor)
489   {
490     mEventActor.TouchSignal().Disconnect( this, &IndicatorEcoreWl::OnTouch );
491   }
492   Disconnect();
493 }
494
495 void IndicatorEcoreWl::SetAdaptor(Adaptor* adaptor)
496 {
497   mAdaptor = adaptor;
498   mIndicatorBuffer->SetAdaptor( adaptor );
499 }
500
501 Dali::Actor IndicatorEcoreWl::GetActor()
502 {
503   return mIndicatorActor;
504 }
505
506 void IndicatorEcoreWl::Open( Dali::Window::WindowOrientation orientation )
507 {
508   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
509
510   // Calls from Window should be set up to ensure we are in a
511   // disconnected state before opening a second time.
512   DALI_ASSERT_DEBUG( mState == DISCONNECTED );
513
514   mOrientation = orientation;
515
516   Connect();
517
518   // Change background visibility depending on orientation
519   if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE  )
520   {
521     if( mBackgroundRenderer )
522     {
523       mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
524       mBackgroundVisible = false;
525     }
526   }
527   else
528   {
529     SetOpacityMode( mOpacityMode );
530   }
531 }
532
533 void IndicatorEcoreWl::Close()
534 {
535   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s", STATE_DEBUG_STRING(mState) );
536
537   if( mState == CONNECTED )
538   {
539     Disconnect();
540     if( mObserver != NULL )
541     {
542       mObserver->IndicatorClosed( this );
543     }
544   }
545
546   Dali::Texture emptyTexture;
547   SetForegroundImage( emptyTexture );
548 }
549
550 void IndicatorEcoreWl::Flicked()
551 {
552   // if indicator is not showing, INDICATOR_FLICK_DONE is given
553   if( mVisible == Dali::Window::AUTO && !mIsShowing )
554   {
555     ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
556   }
557 }
558
559 void IndicatorEcoreWl::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
560 {
561   mOpacityMode = mode;
562
563   Dali::Geometry geometry = CreateBackgroundGeometry();
564   if( geometry )
565   {
566     if( mBackgroundRenderer )
567     {
568       if( mBackgroundRenderer.GetGeometry() != geometry )
569       {
570         mBackgroundRenderer.SetGeometry( geometry );
571       }
572     }
573     else
574     {
575       if( !mBackgroundShader )
576       {
577         mBackgroundShader = Dali::Shader::New( BACKGROUND_VERTEX_SHADER, BACKGROUND_FRAGMENT_SHADER, Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT );
578       }
579
580       mBackgroundRenderer = Dali::Renderer::New( geometry, mBackgroundShader );
581     }
582
583     if( !mBackgroundVisible )
584     {
585       mIndicatorContentActor.AddRenderer( mBackgroundRenderer );
586       mBackgroundVisible = true;
587     }
588   }
589   else if( mBackgroundRenderer )
590   {
591     mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
592     mBackgroundVisible = false;
593   }
594 }
595
596 void IndicatorEcoreWl::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
597 {
598   if ( visibleMode != mVisible || forceUpdate )
599   {
600     // If we were previously hidden, then we should update the image data before we display the indicator
601     if ( mVisible == Dali::Window::INVISIBLE )
602     {
603       UpdateImageData( mCurrentSharedFile );
604     }
605
606     if ( visibleMode == Dali::Window::INVISIBLE )
607     {
608       if (mServerConnection)
609       {
610         mServerConnection->SendEvent( OP_HIDE, NULL, 0 );
611       }
612     }
613     else
614     {
615       mIndicatorActor.SetVisible( true );
616
617       if( mServerConnection )
618       {
619          mServerConnection->SendEvent( OP_SHOW, NULL, 0 );
620       }
621     }
622
623     mVisible = visibleMode;
624
625     if( mForegroundRenderer && mForegroundRenderer.GetTextures().GetTexture( 0u ) )
626     {
627       if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
628       {
629         // hide indicator
630         ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
631       }
632       else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
633       {
634         // show indicator
635         ShowIndicator( KEEP_SHOWING );
636       }
637       else
638       {
639         // hide indicator
640         ShowIndicator( HIDE_NOW );
641       }
642     }
643     else
644     {
645       mIsShowing = false;
646     }
647   }
648 }
649
650 bool IndicatorEcoreWl::IsConnected()
651 {
652   return ( mState == CONNECTED );
653 }
654
655 bool IndicatorEcoreWl::SendMessage( int messageDomain, int messageId, const void *data, int size )
656 {
657  if(IsConnected())
658  {
659    return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
660  }
661  else
662  {
663    return false;
664  }
665 }
666
667 bool IndicatorEcoreWl::OnTouch(Dali::Actor indicator, const Dali::TouchData& touchData)
668 {
669   if( mServerConnection )
670   {
671     // Send touch event to indicator server when indicator is showing
672     if( CheckVisibleState() || mIsShowing )
673     {
674       switch( touchData.GetState(0) )
675       {
676         case Dali::PointState::DOWN:
677         {
678           IpcDataEvMouseMove ipcMove( touchData.GetLocalPosition(0), touchData.GetTime() );
679           IpcDataEvMouseDown ipcDown( touchData.GetTime() );
680           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
681           mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
682
683           if( mVisible == Dali::Window::AUTO )
684           {
685             // Stop hiding indicator
686             ShowIndicator( KEEP_SHOWING );
687           }
688         }
689         break;
690
691         case Dali::PointState::MOTION:
692         {
693           IpcDataEvMouseMove ipcMove( touchData.GetLocalPosition(0), touchData.GetTime() );
694           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
695         }
696         break;
697
698         case Dali::PointState::UP:
699         case Dali::PointState::INTERRUPTED:
700         {
701           IpcDataEvMouseUp ipcUp( touchData.GetTime() );
702           mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
703
704           if( mVisible == Dali::Window::AUTO )
705           {
706             // Hide indicator
707             ShowIndicator( 0.5f /* hide after 0.5 sec */ );
708           }
709         }
710         break;
711
712         case Dali::TouchPoint::Leave:
713         {
714           IpcDataEvMouseMove ipcMove( touchData.GetLocalPosition(0), touchData.GetTime() );
715           mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
716           IpcDataEvMouseUp ipcOut( touchData.GetTime() );
717           mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
718         }
719         break;
720
721         default:
722           break;
723       }
724
725       return true;
726     }
727   }
728
729   return false;
730 }
731
732 bool IndicatorEcoreWl::Connect()
733 {
734   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
735
736   DALI_ASSERT_DEBUG( mState == DISCONNECTED );
737
738   bool connected = false;
739
740   mServerConnection = new ServerConnection( INDICATOR_SERVICE_NAME, 0, false, this );
741   if( mServerConnection )
742   {
743     connected = mServerConnection->IsConnected();
744     if( ! connected )
745     {
746       delete mServerConnection;
747       mServerConnection = NULL;
748     }
749   }
750
751   if( !connected )
752   {
753     StartReconnectionTimer();
754   }
755   else
756   {
757     mState = CONNECTED;
758   }
759
760   return connected;
761 }
762
763 void IndicatorEcoreWl::StartReconnectionTimer()
764 {
765   if( ! mReconnectTimer )
766   {
767     mReconnectTimer = Dali::Timer::New(1000);
768     mConnection.DisconnectAll();
769     mReconnectTimer.TickSignal().Connect( mConnection, &IndicatorEcoreWl::OnReconnectTimer );
770   }
771   mReconnectTimer.Start();
772 }
773
774 bool IndicatorEcoreWl::OnReconnectTimer()
775 {
776   bool retry = false;
777
778   if( mState == DISCONNECTED )
779   {
780     if( !Connect() )
781     {
782       retry = true;
783     }
784   }
785
786   return retry;
787 }
788
789 void IndicatorEcoreWl::Disconnect()
790 {
791   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
792
793   mState = DISCONNECTED;
794
795   delete mServerConnection;
796   mServerConnection = NULL;
797
798   ClearSharedFileInfo();
799 }
800
801 void IndicatorEcoreWl::Resize( int width, int height )
802 {
803   if( width < 1 )
804   {
805     width = 1;
806   }
807   if( height < 1 )
808   {
809     height = 1;
810   }
811
812   if( mImageWidth != width || mImageHeight != height )
813   {
814     mImageWidth = width;
815     mImageHeight = height;
816
817     mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
818     mIndicatorActor.SetSize( mImageWidth, mImageHeight );
819     mEventActor.SetSize(mImageWidth, mImageHeight);
820   }
821 }
822
823 void IndicatorEcoreWl::SetLockFileInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
824 {
825   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
826
827   // epcEvent->ref == w
828   // epcEvent->ref_to == h
829   // epcEvent->response == buffer num
830   // epcEvent->data = lockfile + nul byte
831
832   if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) && (epcEvent->data) &&
833       (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
834   {
835     int n = epcEvent->response;
836
837     if( n >= 0 && n < SHARED_FILE_NUMBER )
838     {
839       mCurrentSharedFile = n;
840
841       mSharedFileInfo[n].mImageWidth  = epcEvent->ref;
842       mSharedFileInfo[n].mImageHeight = epcEvent->ref_to;
843
844       mSharedFileInfo[n].mLockFileName.clear();
845
846       mSharedFileInfo[n].mLockFileName = static_cast< char* >( epcEvent->data );
847
848       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetLockFileInfo: buffer num = %d, w = %d, h = %d, lock = %s\n",
849                      n, mSharedFileInfo[n].mImageWidth, mSharedFileInfo[n].mImageHeight, mSharedFileInfo[n].mLockFileName.c_str() );
850     }
851   }
852 }
853
854 void IndicatorEcoreWl::SetSharedImageInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
855 {
856   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
857
858   // epcEvent->ref == shm id
859   // epcEvent->ref_to == shm num
860   // epcEvent->response == buffer num
861   // epcEvent->data = shm ref string + nul byte
862
863   if ( (epcEvent->data) &&
864        (epcEvent->size > 0) &&
865        (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
866   {
867     int n = epcEvent->response;
868
869     if( n >= 0 && n < SHARED_FILE_NUMBER )
870     {
871       mCurrentSharedFile = n;
872
873       mSharedFileInfo[n].mSharedFileName.clear();
874
875       mSharedFileInfo[n].mSharedFileName = static_cast< char* >( epcEvent->data );
876
877       mSharedFileInfo[n].mSharedFileID = epcEvent->ref;
878       mSharedFileInfo[n].mSharedFileNumber = epcEvent->ref_to;
879
880       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetSharedImageInfo: buffer num %d, shared file = %s, id = %d, num = %d\n",
881                      n, mSharedFileInfo[n].mSharedFileName.c_str(), mSharedFileInfo[n].mSharedFileID, mSharedFileInfo[n].mSharedFileNumber );
882     }
883   }
884 }
885
886 void IndicatorEcoreWl::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
887 {
888   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
889
890   // epcEvent->ref == alpha
891   // epcEvent->ref_to == sys
892   // epcEvent->response == buffer num
893
894   int n = epcEvent->response;
895
896   if( n >= 0 && n < SHARED_FILE_NUMBER )
897   {
898     mCurrentSharedFile = n;
899
900     delete mSharedFileInfo[n].mSharedFile;
901     mSharedFileInfo[n].mSharedFile = NULL;
902
903     delete mSharedFileInfo[n].mLock;
904     mSharedFileInfo[n].mLock = NULL;
905
906     std::stringstream sharedFileID;
907     std::stringstream sharedFileNumber;
908
909     sharedFileID << mSharedFileInfo[n].mSharedFileID;
910     sharedFileNumber << mSharedFileInfo[n].mSharedFileNumber;
911
912     std::string sharedFilename = "/" + mSharedFileInfo[n].mSharedFileName + "-" + sharedFileID.str() + "." + sharedFileNumber.str();
913
914     DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "LoadSharedImage: file name = %s\n", sharedFilename.c_str() );
915
916     mSharedFileInfo[n].mSharedFile = SharedFile::New( sharedFilename.c_str(), mSharedFileInfo[n].mImageWidth * mSharedFileInfo[n].mImageWidth * 4, true );
917     if( mSharedFileInfo[n].mSharedFile != NULL )
918     {
919       mSharedFileInfo[n].mLock = new IndicatorEcoreWl::LockFile( mSharedFileInfo[n].mLockFileName );
920       if( mSharedFileInfo[n].mLock->RetrieveAndClearErrorStatus() )
921       {
922         DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", mSharedFileInfo[n].mLockFileName.c_str() );
923       }
924       else
925       {
926         CreateNewImage( n );
927         UpdateVisibility();
928       }
929     }
930   }
931 }
932
933 void IndicatorEcoreWl::UpdateVisibility()
934 {
935   if( CheckVisibleState() )
936   {
937     // set default indicator type (enable the quick panel)
938     OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
939   }
940   else
941   {
942     // set default indicator type (disable the quick panel)
943     OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
944   }
945
946   if( !mIsShowing )
947   {
948     mIndicatorContentActor.SetPosition( 0.0f, -mImageHeight, 0.0f );
949   }
950
951   SetVisible(mVisible, true);
952 }
953
954 void IndicatorEcoreWl::UpdateImageData( int bufferNumber )
955 {
956   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s  mVisible: %s", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
957
958   if( mState == CONNECTED && mVisible )
959   {
960     // not sure we can skip it when mIsShowing is false
961     CopyToBuffer( bufferNumber );
962   }
963 }
964
965 bool IndicatorEcoreWl::CopyToBuffer( int bufferNumber )
966 {
967   bool success = false;
968
969   if( mSharedFileInfo[bufferNumber].mLock )
970   {
971     IndicatorEcoreWl::ScopedLock scopedLock(mSharedFileInfo[bufferNumber].mLock);
972     if( mSharedFileInfo[bufferNumber].mLock->RetrieveAndClearErrorStatus() )
973     {
974       // Do nothing here.
975     }
976     else if( scopedLock.IsLocked() )
977     {
978       unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
979       size_t size = static_cast< size_t >( mSharedFileInfo[bufferNumber].mImageWidth ) * mSharedFileInfo[bufferNumber].mImageHeight * 4;
980
981       if( mIndicatorBuffer->UpdatePixels( src, size ) )
982       {
983         mAdaptor->RequestUpdateOnce();
984         success = true;
985       }
986     }
987   }
988
989   return success;
990 }
991
992 void IndicatorEcoreWl::CreateNewImage( int bufferNumber )
993 {
994   DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight );
995   mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight, Pixel::BGRA8888 );
996   bool success = false;
997
998   if( CopyToBuffer( bufferNumber ) ) // Only create images if we have valid image buffer
999   {
1000     Dali::Texture texture = Dali::Texture::New( mIndicatorBuffer->GetNativeImage() );
1001     if( texture )
1002     {
1003       SetForegroundImage( texture );
1004       success = true;
1005     }
1006   }
1007
1008   if( !success )
1009   {
1010     DALI_LOG_WARNING("### Cannot create indicator image ###\n");
1011   }
1012 }
1013
1014 Dali::Geometry IndicatorEcoreWl::CreateBackgroundGeometry()
1015 {
1016   switch( mOpacityMode )
1017   {
1018     case Dali::Window::TRANSLUCENT:
1019       if( !mTranslucentGeometry )
1020       {
1021         // Construct 5 interval mesh
1022         // 0  +---+  1
1023         //    | \ |
1024         // 2  +---+  3
1025         //    | \ |
1026         // 4  +---+  5
1027         //    | \ |
1028         // 6  +---+  7
1029         //    | \ |
1030         // 8  +---+  9
1031         //    | \ |
1032         // 10 +---+  11
1033
1034         // Create vertices
1035         struct BackgroundVertex
1036         {
1037           Vector2 mPosition;
1038           float   mAlpha;
1039         };
1040
1041         unsigned int numVertices = 2 * ( NUM_GRADIENT_INTERVALS + 1 );
1042         BackgroundVertex vertices[ numVertices ];
1043
1044         float d = -0.5f;
1045         float delta = 1.0f / NUM_GRADIENT_INTERVALS;
1046         BackgroundVertex* currentVertex = vertices;
1047         for( int y = 0; y < NUM_GRADIENT_INTERVALS + 1; ++y, d += delta )
1048         {
1049           currentVertex->mPosition = Vector2( -0.5f, d );
1050           currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1051           currentVertex++;
1052
1053           currentVertex->mPosition = Vector2( 0.5f, d );
1054           currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1055           currentVertex++;
1056         }
1057
1058         // Create indices
1059         unsigned int numIndices = 2 * 3 * NUM_GRADIENT_INTERVALS;
1060         unsigned short indices[ numIndices ];
1061
1062         unsigned short* currentIndex = indices;
1063         for( int y = 0; y < NUM_GRADIENT_INTERVALS; ++y )
1064         {
1065           *currentIndex++ = (2 * y);
1066           *currentIndex++ = (2 * y) + 3;
1067           *currentIndex++ = (2 * y) + 1;
1068
1069           *currentIndex++ = (2 * y);
1070           *currentIndex++ = (2 * y) + 2;
1071           *currentIndex++ = (2 * y) + 3;
1072         }
1073
1074         Dali::Property::Map vertexFormat;
1075         vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1076         vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1077         Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1078         vertexPropertyBuffer.SetData( vertices, numVertices );
1079
1080         // Create the geometry object
1081         mTranslucentGeometry = Dali::Geometry::New();
1082         mTranslucentGeometry.AddVertexBuffer( vertexPropertyBuffer );
1083         mTranslucentGeometry.SetIndexBuffer( &indices[0], numIndices );
1084       }
1085
1086       return mTranslucentGeometry;
1087     case Dali::Window::OPAQUE:
1088
1089       if( !mSolidGeometry )
1090       {
1091         // Create vertices
1092         struct BackgroundVertex
1093         {
1094           Vector2 mPosition;
1095           float   mAlpha;
1096         };
1097
1098         BackgroundVertex vertices[ 4 ] = { { Vector2( -0.5f, -0.5f ), 1.0f }, { Vector2( 0.5f, -0.5f ), 1.0f },
1099                                            { Vector2( -0.5f,  0.5f ), 1.0f }, { Vector2( 0.5f,  0.5f ), 1.0f } };
1100
1101         // Create indices
1102         unsigned short indices[ 6 ] = { 0, 3, 1, 0, 2, 3 };
1103
1104         Dali::Property::Map vertexFormat;
1105         vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1106         vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1107         Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1108         vertexPropertyBuffer.SetData( vertices, 4 );
1109
1110
1111         // Create the geometry object
1112         mSolidGeometry = Dali::Geometry::New();
1113         mSolidGeometry.AddVertexBuffer( vertexPropertyBuffer );
1114         mSolidGeometry.SetIndexBuffer( &indices[0], 6 );
1115       }
1116
1117       return mSolidGeometry;
1118     case Dali::Window::TRANSPARENT:
1119       break;
1120   }
1121
1122   return Dali::Geometry();
1123 }
1124
1125 void IndicatorEcoreWl::SetForegroundImage( Dali::Texture texture )
1126 {
1127   if( !mForegroundRenderer && texture )
1128   {
1129     // Create Shader
1130     Dali::Shader shader = Dali::Shader::New( FOREGROUND_VERTEX_SHADER, FOREGROUND_FRAGMENT_SHADER );
1131
1132     // Create renderer from geometry and material
1133     Dali::Geometry quad = CreateQuadGeometry();
1134     mForegroundRenderer = Dali::Renderer::New( quad, shader );
1135     // Make sure the foreground stays in front of the background
1136     mForegroundRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, 1.f );
1137
1138     // Set blend function
1139     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_RGB,    Dali::BlendFactor::ONE );
1140     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_RGB,   Dali::BlendFactor::ONE_MINUS_SRC_ALPHA );
1141     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_ALPHA,  Dali::BlendFactor::ONE );
1142     mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_ALPHA, Dali::BlendFactor::ONE );
1143
1144     // Create a texture-set and add to renderer
1145
1146     Dali::TextureSet textureSet = Dali::TextureSet::New();
1147     textureSet.SetTexture( 0u, texture );
1148     mForegroundRenderer.SetTextures( textureSet );
1149
1150     mIndicatorContentActor.AddRenderer( mForegroundRenderer );
1151   }
1152   else if( mForegroundRenderer )
1153   {
1154     Dali::TextureSet textureSet = mForegroundRenderer.GetTextures();
1155     textureSet.SetTexture( 0u, texture );
1156   }
1157
1158   if( mImageWidth == 0 && mImageHeight == 0  && texture)
1159   {
1160     Resize( texture.GetWidth(), texture.GetHeight() );
1161   }
1162 }
1163
1164 void IndicatorEcoreWl::OnIndicatorTypeChanged( Type indicatorType )
1165 {
1166   if( mObserver != NULL )
1167   {
1168     mObserver->IndicatorTypeChanged( indicatorType );
1169   }
1170 }
1171
1172 void IndicatorEcoreWl::DataReceived( void* event )
1173 {
1174   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1175   Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1176
1177   switch( epcEvent->minor )
1178   {
1179     case OP_UPDATE:
1180     {
1181       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1182       if( mIsShowing )
1183       {
1184         mAdaptor->RequestUpdateOnce();
1185       }
1186       break;
1187     }
1188     case OP_UPDATE_DONE:
1189     {
1190       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
1191       // epcEvent->response == display buffer #
1192       UpdateImageData( epcEvent->response );
1193       break;
1194     }
1195     case OP_SHM_REF0:
1196     {
1197       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF0\n" );
1198       SetSharedImageInfo( epcEvent );
1199       break;
1200     }
1201     case OP_SHM_REF1:
1202     {
1203       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF1\n" );
1204       SetLockFileInfo( epcEvent );
1205       break;
1206     }
1207     case OP_SHM_REF2:
1208     {
1209       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF2\n" );
1210       LoadSharedImage( epcEvent );
1211       break;
1212     }
1213     case OP_RESIZE:
1214     {
1215       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1216
1217       if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1218       {
1219         IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1220         Resize( newSize->w, newSize->h );
1221       }
1222       break;
1223     }
1224     case OP_MSG_PARENT:
1225     {
1226       int msgDomain = epcEvent->ref;
1227       int msgId = epcEvent->ref_to;
1228
1229       void *msgData = NULL;
1230       int msgDataSize = 0;
1231       msgData = epcEvent->data;
1232       msgDataSize = epcEvent->size;
1233
1234       DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT. msgDomain = %d\n", msgDomain );
1235
1236       if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1237       {
1238         switch( msgId )
1239         {
1240           case MSG_ID_INDICATOR_TYPE:
1241           {
1242             DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1243             Type* indicatorType = static_cast<Type*>( epcEvent->data );
1244             OnIndicatorTypeChanged( *indicatorType );
1245             break;
1246           }
1247
1248           case MSG_ID_INDICATOR_START_ANIMATION:
1249           {
1250             DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: MSG_ID_INDICATOR_START_ANIMATION\n" );
1251
1252             if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1253             {
1254               DALI_LOG_ERROR("Message data is incorrect\n");
1255               break;
1256             }
1257
1258             IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1259
1260             if(!CheckVisibleState())
1261             {
1262               ShowIndicator( animData->duration /* n sec */ );
1263             }
1264             break;
1265           }
1266         }
1267       }
1268       break;
1269     }
1270   }
1271 }
1272
1273 void IndicatorEcoreWl::ConnectionClosed()
1274 {
1275   DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1276
1277   // Will get this callback if the server connection failed to start up.
1278   delete mServerConnection;
1279   mServerConnection = NULL;
1280   mState = DISCONNECTED;
1281
1282   // Attempt to re-connect
1283   Connect();
1284 }
1285
1286 bool IndicatorEcoreWl::CheckVisibleState()
1287 {
1288   if( mOrientation == Dali::Window::LANDSCAPE
1289     || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1290     || (mVisible == Dali::Window::INVISIBLE)
1291     || (mVisible == Dali::Window::AUTO && !mIsShowing) )
1292   {
1293     return false;
1294   }
1295
1296   return true;
1297 }
1298
1299 void IndicatorEcoreWl::ClearSharedFileInfo()
1300 {
1301   for( int i = 0; i < SHARED_FILE_NUMBER; i++ )
1302   {
1303     delete mSharedFileInfo[i].mLock;
1304     mSharedFileInfo[i].mLock = NULL;
1305
1306     delete mSharedFileInfo[i].mSharedFile;
1307     mSharedFileInfo[i].mSharedFile = NULL;
1308
1309     mSharedFileInfo[i].mLockFileName.clear();
1310     mSharedFileInfo[i].mSharedFileName.clear();
1311   }
1312 }
1313
1314 /**
1315  * duration can be this
1316  *
1317  * enum
1318  * {
1319  *  KEEP_SHOWING = -1,
1320  *  HIDE_NOW = 0
1321  * };
1322  */
1323 void IndicatorEcoreWl::ShowIndicator(float duration)
1324 {
1325   if( !mIndicatorAnimation )
1326   {
1327     mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1328     mIndicatorAnimation.FinishedSignal().Connect(this, &IndicatorEcoreWl::OnAnimationFinished);
1329   }
1330
1331   if(mIsShowing && !EqualsZero(duration))
1332   {
1333     // If need to show during showing, do nothing.
1334     // In 2nd phase (below) will update timer
1335   }
1336   else if(!mIsShowing && mIsAnimationPlaying && EqualsZero(duration))
1337   {
1338     // If need to hide during hiding or hidden already, do nothing
1339   }
1340   else
1341   {
1342     mIndicatorAnimation.Clear();
1343
1344     if( EqualsZero(duration) )
1345     {
1346       mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, -mImageHeight, 0), Dali::AlphaFunction::EASE_OUT );
1347
1348       mIsShowing = false;
1349
1350       OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1351     }
1352     else
1353     {
1354       mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, 0, 0), Dali::AlphaFunction::EASE_OUT );
1355
1356       mIsShowing = true;
1357
1358       OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1359     }
1360
1361     mIndicatorAnimation.Play();
1362     mIsAnimationPlaying = true;
1363   }
1364
1365   if(duration > 0)
1366   {
1367     if(!mShowTimer)
1368     {
1369       mShowTimer = Dali::Timer::New(1000 * duration);
1370       mShowTimer.TickSignal().Connect(this, &IndicatorEcoreWl::OnShowTimer);
1371     }
1372     mShowTimer.SetInterval(1000* duration);
1373     mShowTimer.Start();
1374
1375     if( mVisible == Dali::Window::AUTO )
1376     {
1377       // check the stage touch
1378       Dali::Stage::GetCurrent().TouchSignal().Connect( this, &IndicatorEcoreWl::OnStageTouch );
1379     }
1380   }
1381   else
1382   {
1383     if(mShowTimer && mShowTimer.IsRunning())
1384     {
1385       mShowTimer.Stop();
1386     }
1387
1388     if( mVisible == Dali::Window::AUTO )
1389     {
1390       // check the stage touch
1391       Dali::Stage::GetCurrent().TouchSignal().Disconnect( this, &IndicatorEcoreWl::OnStageTouch );
1392     }
1393   }
1394 }
1395
1396 bool IndicatorEcoreWl::OnShowTimer()
1397 {
1398   // after time up, hide indicator
1399   ShowIndicator( HIDE_NOW );
1400
1401   return false;
1402 }
1403
1404 void IndicatorEcoreWl::OnAnimationFinished(Dali::Animation& animation)
1405 {
1406   mIsAnimationPlaying = false;
1407   // once animation is finished and indicator is hidden, take it off stage
1408   if( mObserver != NULL )
1409   {
1410     mObserver->IndicatorVisibilityChanged( mIsShowing ); // is showing?
1411   }
1412 }
1413
1414 void IndicatorEcoreWl::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
1415 {
1416   // Nothing to do, but we still want to consume pan
1417 }
1418
1419 void IndicatorEcoreWl::OnStageTouch(const Dali::TouchData& touchData)
1420 {
1421   // when stage is touched while indicator is showing temporary, hide it
1422   if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1423   {
1424     switch( touchData.GetState(0) )
1425     {
1426       case Dali::PointState::DOWN:
1427       {
1428         // if touch point is inside the indicator, indicator is not hidden
1429         if( mImageHeight < int( touchData.GetScreenPosition(0).y ) )
1430         {
1431           ShowIndicator( HIDE_NOW );
1432         }
1433         break;
1434       }
1435
1436       default:
1437       break;
1438     }
1439   }
1440 }
1441
1442 } // Adaptor
1443
1444 } // Internal
1445
1446 } // Dali
1447
1448 #pragma GCC diagnostic pop