2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "ecore-indicator-impl.h"
24 #include <Ecore_Wayland.h>
26 #include <sys/types.h>
32 #include <dali/public-api/images/native-image.h>
33 #include <dali/public-api/events/touch-data.h>
34 #include <dali/public-api/common/stage.h>
35 #include <dali/public-api/images/buffer-image.h>
36 #include <dali/devel-api/images/texture-set-image.h>
37 #include <dali/integration-api/debug.h>
39 #include <tbm_surface.h>
40 #include <wayland-extension/tizen-remote-surface-client-protocol.h>
41 #include <wayland-client.h>
42 #include <wayland-tbm-client.h>
45 #include <adaptor-impl.h>
46 #include <accessibility-adaptor-impl.h>
47 #include <native-image-source.h>
51 #if defined(DEBUG_ENABLED)
52 #define STATE_DEBUG_STRING(state) (state==DISCONNECTED?"DISCONNECTED":state==CONNECTED?"CONNECTED":"UNKNOWN")
58 const float SLIDING_ANIMATION_DURATION( 0.2f ); // 200 milli seconds
59 const float AUTO_INDICATOR_STAY_DURATION(3.0f); // 3 seconds
60 const float SHOWING_DISTANCE_HEIGHT_RATE(0.34f); // 20 pixels
68 const int NUM_GRADIENT_INTERVALS(5); // Number of gradient intervals
69 const float GRADIENT_ALPHA[NUM_GRADIENT_INTERVALS+1] = { 0.6f, 0.38f, 0.20f, 0.08f, 0.0f, 0.0f };
71 #define MAKE_SHADER(A)#A
73 const char* BACKGROUND_VERTEX_SHADER = MAKE_SHADER(
74 attribute mediump vec2 aPosition;
75 attribute mediump float aAlpha;
76 varying mediump float vAlpha;
77 uniform mediump mat4 uMvpMatrix;
78 uniform mediump vec3 uSize;
82 mediump vec4 vertexPosition = vec4( aPosition * uSize.xy, 0.0, 1.0 );
83 vertexPosition = uMvpMatrix * vertexPosition;
86 gl_Position = vertexPosition;
90 const char* BACKGROUND_FRAGMENT_SHADER = MAKE_SHADER(
91 uniform lowp vec4 uColor;
92 varying mediump float vAlpha;
96 gl_FragColor = uColor;
97 gl_FragColor.a *= vAlpha;
101 const char* FOREGROUND_VERTEX_SHADER = DALI_COMPOSE_SHADER(
102 attribute mediump vec2 aPosition;\n
103 varying mediump vec2 vTexCoord;\n
104 uniform mediump mat4 uMvpMatrix;\n
105 uniform mediump vec3 uSize;\n
106 uniform mediump vec4 sTextureRect;\n
110 gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n
111 vTexCoord = aPosition + vec2(0.5);\n
115 const char* FOREGROUND_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
116 varying mediump vec2 vTexCoord;\n
117 uniform sampler2D sTexture;\n
121 gl_FragColor = texture2D( sTexture, vTexCoord );\n // the foreground does not apply actor color
125 const char* FOREGROUND_TBM_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
126 varying mediump vec2 vTexCoord;\n
127 uniform samplerExternalOES sTexture;\n
131 gl_FragColor = texture2D( sTexture, vTexCoord );\n // the foreground does not apply actor color
135 Dali::Geometry CreateQuadGeometry()
137 Dali::Property::Map quadVertexFormat;
138 quadVertexFormat["aPosition"] = Dali::Property::VECTOR2;
139 Dali::PropertyBuffer vertexData = Dali::PropertyBuffer::New( quadVertexFormat );
141 const float halfQuadSize = .5f;
142 struct QuadVertex { Dali::Vector2 position; };
143 QuadVertex quadVertexData[4] = {
144 { Dali::Vector2(-halfQuadSize, -halfQuadSize) },
145 { Dali::Vector2(-halfQuadSize, halfQuadSize) },
146 { Dali::Vector2( halfQuadSize, -halfQuadSize) },
147 { Dali::Vector2( halfQuadSize, halfQuadSize) } };
148 vertexData.SetData(quadVertexData, 4);
150 Dali::Geometry quad = Dali::Geometry::New();
151 quad.AddVertexBuffer( vertexData );
152 quad.SetType( Dali::Geometry::TRIANGLE_STRIP );
156 const float OPAQUE_THRESHOLD(0.99f);
157 const float TRANSPARENT_THRESHOLD(0.05f);
159 // indicator service name
160 const char* INDICATOR_SERVICE_NAME("elm_indicator");
162 // Copied from ecore_evas_extn_engine.h
178 OP_PROFILE_CHANGE_REQUEST,
179 OP_PROFILE_CHANGE_DONE,
197 // Copied from elm_conform.c
199 const int MSG_DOMAIN_CONTROL_INDICATOR( 0x10001 );
200 const int MSG_ID_INDICATOR_REPEAT_EVENT( 0x10002 );
201 const int MSG_ID_INDICATOR_ROTATION( 0x10003 );
202 const int MSG_ID_INDICATOR_OPACITY( 0X1004 );
203 const int MSG_ID_INDICATOR_TYPE( 0X1005 );
204 const int MSG_ID_INDICATOR_START_ANIMATION( 0X10006 );
216 struct IpcIndicatorDataAnimation
222 struct IpcDataEvMouseUp
225 Evas_Button_Flags flags;
227 unsigned int timestamp;
228 Evas_Event_Flags event_flags;
230 IpcDataEvMouseUp(unsigned long timestamp)
232 flags(EVAS_BUTTON_NONE),
234 timestamp(static_cast<unsigned int>(timestamp)),
235 event_flags(EVAS_EVENT_FLAG_NONE)
240 struct IpcDataEvMouseDown
243 Evas_Button_Flags flags;
245 unsigned int timestamp;
246 Evas_Event_Flags event_flags;
248 IpcDataEvMouseDown(unsigned long timestamp)
250 flags(EVAS_BUTTON_NONE),
252 timestamp(static_cast<unsigned int>(timestamp)),
253 event_flags(EVAS_EVENT_FLAG_NONE)
258 struct IpcDataEvMouseMove
261 Evas_Button_Flags flags;
263 unsigned int timestamp;
264 Evas_Event_Flags event_flags;
266 IpcDataEvMouseMove(const Dali::TouchData& touchData, unsigned long timestamp)
267 : x(static_cast<Evas_Coord>(touchData.GetLocalPosition( 0 ).x)),
268 y(static_cast<Evas_Coord>(touchData.GetLocalPosition( 0 ).y)),
269 flags(EVAS_BUTTON_NONE),
271 timestamp(static_cast<unsigned int>(timestamp)),
272 event_flags(EVAS_EVENT_FLAG_NONE)
277 struct IpcDataEvMouseOut
279 unsigned int timestamp;
281 Evas_Event_Flags event_flags;
283 IpcDataEvMouseOut(unsigned long timestamp)
284 : timestamp(static_cast<unsigned int>(timestamp)),
286 event_flags(EVAS_EVENT_FLAG_NONE)
291 struct wl_buffer* preBuffer;
293 static void OnUpdateIndicatorImage( void* data, struct tizen_remote_surface* remoteSurface, struct wl_buffer* buffer, uint32_t time )
295 Dali::Internal::Adaptor::Indicator* indicator = static_cast< Dali::Internal::Adaptor::Indicator* >( data );
299 tbm_surface_h tbmSurface = static_cast< tbm_surface_h >( wl_buffer_get_user_data( buffer ) );
301 indicator->UpdateIndicatorImage( tbmSurface );
304 if( preBuffer != NULL && tizen_remote_surface_get_version( remoteSurface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
306 tizen_remote_surface_release( remoteSurface, preBuffer );
312 static void OnMissingIndicatorImage( void* data, struct tizen_remote_surface* surface )
314 DALI_LOG_ERROR( "Missing indicator remote surface\n" );
317 static void OnChangedIndicatorImage( void* data, struct tizen_remote_surface* remoteSurface, uint32_t type, struct wl_buffer* buffer,
318 int32_t fd, uint32_t fileSize, uint32_t time, struct wl_array* keys )
320 Dali::Internal::Adaptor::Indicator* indicator = static_cast< Dali::Internal::Adaptor::Indicator* >( data );
322 if( indicator && type == TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM )
324 tbm_surface_h tbmSurface = static_cast< tbm_surface_h >( wl_buffer_get_user_data( buffer ) );
326 indicator->UpdateIndicatorImage( tbmSurface );
329 if( preBuffer != NULL && tizen_remote_surface_get_version( remoteSurface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
331 tizen_remote_surface_release( remoteSurface, preBuffer );
339 static const struct tizen_remote_surface_listener remoteSurfaceCallback =
341 OnUpdateIndicatorImage,
342 OnMissingIndicatorImage,
343 OnChangedIndicatorImage,
346 } // anonymous namespace
355 #if defined(DEBUG_ENABLED)
356 Debug::Filter* gIndicatorLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_INDICATOR");
359 // Impl to hide EFL implementation.
361 struct Indicator::Impl
363 enum // operation mode
366 INDICATOR_STAY_WITH_DURATION
372 Impl(Indicator* indicator)
373 : mIndicator(indicator),
374 mEcoreEventHandler(NULL)
376 #if defined(DALI_PROFILE_MOBILE)
377 mEcoreEventHandler = ecore_event_handler_add(ECORE_WL_EVENT_INDICATOR_FLICK, EcoreEventIndicator, this);
378 #endif // WAYLAND && DALI_PROFILE_MOBILE
386 if ( mEcoreEventHandler )
388 ecore_event_handler_del(mEcoreEventHandler);
392 static void SetIndicatorVisibility( void* data, int operation )
394 Indicator::Impl* indicatorImpl((Indicator::Impl*)data);
396 if ( indicatorImpl == NULL || indicatorImpl->mIndicator == NULL)
400 if ( operation == INDICATOR_STAY_WITH_DURATION )
402 // if indicator is not showing, INDICATOR_FLICK_DONE is given
403 if( indicatorImpl->mIndicator->mVisible == Dali::Window::AUTO &&
404 !indicatorImpl->mIndicator->mIsShowing )
406 indicatorImpl->mIndicator->ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
409 else if( operation == INDICATOR_HIDE )
411 if( indicatorImpl->mIndicator->mVisible == Dali::Window::AUTO &&
412 indicatorImpl->mIndicator->mIsShowing )
414 indicatorImpl->mIndicator->ShowIndicator( HIDE_NOW );
418 #if defined(DALI_PROFILE_MOBILE)
420 * Called when the Ecore indicator event is received.
422 static Eina_Bool EcoreEventIndicator( void* data, int type, void* event )
424 SetIndicatorVisibility( data, INDICATOR_STAY_WITH_DURATION );
425 return ECORE_CALLBACK_PASS_ON;
427 #endif // WAYLAND && DALI_PROFILE_MOBILE
430 Indicator* mIndicator;
431 Ecore_Event_Handler* mEcoreEventHandler;
434 Indicator::LockFile::LockFile(const std::string filename)
435 : mFilename(filename),
438 mFileDescriptor = open(filename.c_str(), O_RDWR);
439 if( mFileDescriptor == -1 )
443 DALI_LOG_ERROR( "### Cannot open %s for indicator lock ###\n", mFilename.c_str() );
447 Indicator::LockFile::~LockFile()
449 // Closing file descriptor also unlocks file.
450 close( mFileDescriptor );
453 bool Indicator::LockFile::Lock()
455 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
458 if( mFileDescriptor > 0 )
460 struct flock filelock;
462 filelock.l_type = F_RDLCK;
463 filelock.l_whence = SEEK_SET;
464 filelock.l_start = 0;
466 if( fcntl( mFileDescriptor, F_SETLKW, &filelock ) == -1 )
469 DALI_LOG_ERROR( "### Failed to lock with fd : %s ###\n", mFilename.c_str() );
479 DALI_LOG_ERROR( "### Invalid fd ###\n" );
485 void Indicator::LockFile::Unlock()
487 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
489 struct flock filelock;
491 filelock.l_type = F_UNLCK;
492 filelock.l_whence = SEEK_SET;
493 filelock.l_start = 0;
495 if (fcntl(mFileDescriptor, F_SETLKW, &filelock) == -1)
498 DALI_LOG_ERROR( "### Failed to lock with fd : %s ###\n", mFilename.c_str() );
502 bool Indicator::LockFile::RetrieveAndClearErrorStatus()
504 bool error = mErrorThrown;
505 mErrorThrown = false;
509 Indicator::ScopedLock::ScopedLock(LockFile* lockFile)
510 : mLockFile(lockFile),
515 mLocked = mLockFile->Lock();
519 Indicator::ScopedLock::~ScopedLock()
527 bool Indicator::ScopedLock::IsLocked()
532 Indicator::Indicator( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, IndicatorInterface::Observer* observer )
534 mGestureDeltaY( 0.0f ),
535 mGestureDetected( false ),
537 mOpacityMode( Dali::Window::OPAQUE ),
538 mState( DISCONNECTED ),
540 mServerConnection( NULL ),
541 mObserver( observer ),
542 mOrientation( orientation ),
545 mVisible( Dali::Window::INVISIBLE ),
547 mIsAnimationPlaying( false ),
548 mCurrentSharedFile( 0 ),
549 mSharedBufferType( BUFFER_TYPE_SHM ),
551 mBackgroundVisible( false ),
554 mIndicatorContentActor = Dali::Actor::New();
555 mIndicatorContentActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
556 mIndicatorContentActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
558 // Indicator image handles the touch event including "leave"
559 mIndicatorContentActor.SetLeaveRequired( true );
560 mIndicatorContentActor.TouchSignal().Connect( this, &Indicator::OnTouched );
561 mIndicatorContentActor.SetColor( Color::BLACK );
563 mIndicatorActor = Dali::Actor::New();
564 mIndicatorActor.Add( mIndicatorContentActor );
566 // Event handler to find out flick down gesture
567 mEventActor = Dali::Actor::New();
568 mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
569 mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
570 mIndicatorActor.Add( mEventActor );
572 // Attach pan gesture to find flick down during hiding.
573 // It can prevent the problem that scrollview gets pan gesture even indicator area is touched,
574 // since it consumes the pan gesture in advance.
575 mPanDetector = Dali::PanGestureDetector::New();
576 mPanDetector.DetectedSignal().Connect( this, &Indicator::OnPan );
577 mPanDetector.Attach( mEventActor );
581 // register indicator to accessibility adaptor
582 Dali::AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
583 if(accessibilityAdaptor)
585 AccessibilityAdaptor::GetImplementation( accessibilityAdaptor ).SetIndicator( this );
587 // hide the indicator by default
588 mIndicatorActor.SetVisible( false );
590 // create impl to handle ecore event
591 mImpl = new Impl(this);
594 Indicator::~Indicator()
604 mEventActor.TouchSignal().Disconnect( this, &Indicator::OnTouched );
609 void Indicator::SetAdaptor(Adaptor* adaptor)
612 mIndicatorBuffer->SetAdaptor( adaptor );
615 Dali::Actor Indicator::GetActor()
617 return mIndicatorActor;
620 void Indicator::Open( Dali::Window::WindowOrientation orientation )
622 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
624 // Calls from Window should be set up to ensure we are in a
625 // disconnected state before opening a second time.
626 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
628 mOrientation = orientation;
632 // Change background visibility depending on orientation
633 if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE )
635 if( mBackgroundRenderer )
637 mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
638 mBackgroundVisible = false;
643 SetOpacityMode( mOpacityMode );
647 void Indicator::Close()
649 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s", STATE_DEBUG_STRING(mState) );
651 if( mState == CONNECTED )
654 if( mObserver != NULL )
656 mObserver->IndicatorClosed( this );
660 Dali::Texture emptyTexture;
661 SetForegroundImage( emptyTexture );
664 void Indicator::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
668 Dali::Geometry geometry = CreateBackgroundGeometry();
671 if( mBackgroundRenderer )
673 if( mBackgroundRenderer.GetGeometry() != geometry )
675 mBackgroundRenderer.SetGeometry( geometry );
680 if( !mBackgroundShader )
682 mBackgroundShader = Dali::Shader::New( BACKGROUND_VERTEX_SHADER, BACKGROUND_FRAGMENT_SHADER, Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT );
685 mBackgroundRenderer = Dali::Renderer::New( geometry, mBackgroundShader );
688 if( !mBackgroundVisible )
690 mIndicatorContentActor.AddRenderer( mBackgroundRenderer );
691 mBackgroundVisible = true;
694 else if( mBackgroundRenderer )
696 mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
697 mBackgroundVisible = false;
702 void Indicator::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
704 if ( visibleMode != mVisible || forceUpdate )
706 // If we were previously hidden, then we should update the image data before we display the indicator
707 if ( mVisible == Dali::Window::INVISIBLE )
709 UpdateImageData( mCurrentSharedFile );
712 if ( visibleMode == Dali::Window::INVISIBLE )
714 if (mServerConnection)
716 mServerConnection->SendEvent( OP_HIDE, NULL, 0 );
721 mIndicatorActor.SetVisible( true );
723 if( mServerConnection )
725 mServerConnection->SendEvent( OP_SHOW, NULL, 0 );
729 mVisible = visibleMode;
732 if( mForegroundRenderer &&
733 ( mForegroundRenderer.GetTextures().GetTexture( 0u ) ||
734 Dali::TextureGetImage( mForegroundRenderer.GetTextures(), 0u ) )
737 if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
740 ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
742 else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
745 ShowIndicator( KEEP_SHOWING );
750 ShowIndicator( HIDE_NOW );
760 bool Indicator::IsConnected()
762 return ( mState == CONNECTED );
765 bool Indicator::SendMessage( int messageDomain, int messageId, const void *data, int size )
769 return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
777 bool Indicator::OnTouched(Dali::Actor indicator, const Dali::TouchData& touchData)
779 if( mServerConnection )
781 // Send touch event to indicator server when indicator is showing
782 if( CheckVisibleState() || mIsShowing )
784 switch( touchData.GetState( 0 ) )
786 case Dali::PointState::DOWN:
788 IpcDataEvMouseMove ipcMove( touchData, touchData.GetTime() );
789 IpcDataEvMouseDown ipcDown( touchData.GetTime() );
790 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
791 mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
793 if( mVisible == Dali::Window::AUTO )
795 // Stop hiding indicator
796 ShowIndicator( KEEP_SHOWING );
801 case Dali::PointState::MOTION:
803 IpcDataEvMouseMove ipcMove( touchData, touchData.GetTime() );
804 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
808 case Dali::PointState::UP:
809 case Dali::PointState::INTERRUPTED:
811 IpcDataEvMouseUp ipcUp( touchData.GetTime() );
812 mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
814 if( mVisible == Dali::Window::AUTO )
817 ShowIndicator( 0.5f /* hide after 0.5 sec */ );
822 case Dali::PointState::LEAVE:
824 IpcDataEvMouseMove ipcMove( touchData, touchData.GetTime() );
825 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
826 IpcDataEvMouseUp ipcOut( touchData.GetTime() );
827 mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
842 bool Indicator::Connect()
844 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
846 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
848 bool connected = false;
850 mServerConnection = new ServerConnection( INDICATOR_SERVICE_NAME, 0, false, this );
851 if( mServerConnection )
853 connected = mServerConnection->IsConnected();
856 delete mServerConnection;
857 mServerConnection = NULL;
863 StartReconnectionTimer();
873 void Indicator::StartReconnectionTimer()
875 if( ! mReconnectTimer )
877 mReconnectTimer = Dali::Timer::New(1000);
878 mConnection.DisconnectAll();
879 mReconnectTimer.TickSignal().Connect( mConnection, &Indicator::OnReconnectTimer );
881 mReconnectTimer.Start();
884 bool Indicator::OnReconnectTimer()
888 if( mState == DISCONNECTED )
899 void Indicator::Disconnect()
901 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
903 mState = DISCONNECTED;
905 delete mServerConnection;
906 mServerConnection = NULL;
908 ClearSharedFileInfo();
911 void Indicator::Resize( int width, int height )
922 if( mImageWidth != width || mImageHeight != height )
925 mImageHeight = height;
927 mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
928 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
929 mEventActor.SetSize(mImageWidth, mImageHeight);
934 void Indicator::SetLockFileInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
936 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
938 // epcEvent->ref == w
939 // epcEvent->ref_to == h
940 // epcEvent->response == buffer num
941 // epcEvent->data = lockfile + nul byte
943 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) && (epcEvent->data) &&
944 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
946 int n = epcEvent->response;
948 if( n >= 0 && n < SHARED_FILE_NUMBER )
950 mCurrentSharedFile = n;
952 mSharedFileInfo[n].mImageWidth = epcEvent->ref;
953 mSharedFileInfo[n].mImageHeight = epcEvent->ref_to;
955 mSharedFileInfo[n].mLockFileName.clear();
957 mSharedFileInfo[n].mLockFileName = static_cast< char* >( epcEvent->data );
959 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetLockFileInfo: buffer num = %d, w = %d, h = %d, lock = %s\n",
960 n, mSharedFileInfo[n].mImageWidth, mSharedFileInfo[n].mImageHeight, mSharedFileInfo[n].mLockFileName.c_str() );
965 void Indicator::SetSharedImageInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
967 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
969 // epcEvent->ref == shm id
970 // epcEvent->ref_to == shm num
971 // epcEvent->response == buffer num
972 // epcEvent->data = shm ref string + nul byte
974 if ( (epcEvent->data) &&
975 (epcEvent->size > 0) &&
976 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
978 int n = epcEvent->response;
980 if( n >= 0 && n < SHARED_FILE_NUMBER )
982 mCurrentSharedFile = n;
984 mSharedFileInfo[n].mSharedFileName.clear();
986 mSharedFileInfo[n].mSharedFileName = static_cast< char* >( epcEvent->data );
988 mSharedFileInfo[n].mSharedFileID = epcEvent->ref;
989 mSharedFileInfo[n].mSharedFileNumber = epcEvent->ref_to;
991 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetSharedImageInfo: buffer num %d, shared file = %s, id = %d, num = %d\n",
992 n, mSharedFileInfo[n].mSharedFileName.c_str(), mSharedFileInfo[n].mSharedFileID, mSharedFileInfo[n].mSharedFileNumber );
997 void Indicator::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
999 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1001 // epcEvent->ref == alpha
1002 // epcEvent->ref_to == sys
1003 // epcEvent->response == buffer num
1005 if ( mSharedBufferType != BUFFER_TYPE_SHM )
1010 int n = epcEvent->response;
1012 if( n >= 0 && n < SHARED_FILE_NUMBER )
1014 mCurrentSharedFile = n;
1016 delete mSharedFileInfo[n].mSharedFile;
1017 mSharedFileInfo[n].mSharedFile = NULL;
1019 delete mSharedFileInfo[n].mLock;
1020 mSharedFileInfo[n].mLock = NULL;
1022 std::stringstream sharedFileID;
1023 std::stringstream sharedFileNumber;
1025 sharedFileID << mSharedFileInfo[n].mSharedFileID;
1026 sharedFileNumber << mSharedFileInfo[n].mSharedFileNumber;
1028 std::string sharedFilename = "/" + mSharedFileInfo[n].mSharedFileName + "-" + sharedFileID.str() + "." + sharedFileNumber.str();
1030 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "LoadSharedImage: file name = %s\n", sharedFilename.c_str() );
1032 mSharedFileInfo[n].mSharedFile = SharedFile::New( sharedFilename.c_str(), mSharedFileInfo[n].mImageWidth * mSharedFileInfo[n].mImageWidth * 4, true );
1033 if( mSharedFileInfo[n].mSharedFile != NULL )
1035 mSharedFileInfo[n].mLock = new Indicator::LockFile( mSharedFileInfo[n].mLockFileName );
1036 if( mSharedFileInfo[n].mLock->RetrieveAndClearErrorStatus() )
1038 DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", mSharedFileInfo[n].mLockFileName.c_str() );
1043 CreateNewImage( n );
1049 void Indicator::SetupNativeIndicatorImage( Ecore_Ipc_Event_Server_Data *epcEvent )
1051 // Bind tizen remote surface
1052 Eina_Inlist* globals;
1053 Ecore_Wl_Global* global;
1054 struct tizen_remote_surface_manager* remoteSurfaceManager = NULL;
1055 struct tizen_remote_surface* remoteSurface = NULL;
1056 struct wl_registry* registry;
1057 struct wayland_tbm_client* tbmClient;
1058 struct wl_tbm* wlTbm;
1060 if ( !remoteSurfaceManager )
1062 registry = ecore_wl_registry_get();
1063 globals = ecore_wl_globals_get();
1065 if (!registry || !globals)
1067 DALI_LOG_ERROR( "SetupNativeIndicatorImage registry or globals error\n" );
1071 EINA_INLIST_FOREACH(globals, global)
1073 if ( !strcmp( global->interface, "tizen_remote_surface_manager" ) )
1075 remoteSurfaceManager = ( struct tizen_remote_surface_manager* )wl_registry_bind( registry, global->id, &tizen_remote_surface_manager_interface, ( ( global->version < 3 )? global->version: 3 ) );
1079 if ( !remoteSurfaceManager )
1081 DALI_LOG_ERROR( "SetupNativeIndicatorImage bind error\n" );
1085 tbmClient = ( struct wayland_tbm_client* )wayland_tbm_client_init( ecore_wl_display_get() );
1088 DALI_LOG_ERROR( "SetupNativeIndicatorImage client init error\n" );
1092 wlTbm = ( struct wl_tbm* )wayland_tbm_client_get_wl_tbm( tbmClient );
1095 DALI_LOG_ERROR( "SetupNativeIndicatorImage wl tbm error\n" );
1099 uint32_t resourceId = epcEvent->ref;
1100 remoteSurface = tizen_remote_surface_manager_create_surface( remoteSurfaceManager, resourceId, wlTbm );
1102 if( !remoteSurface )
1104 DALI_LOG_ERROR( "SetupNativeIndicatorImage create surface error\n" );
1108 tizen_remote_surface_add_listener( remoteSurface, &remoteSurfaceCallback, this );
1109 tizen_remote_surface_redirect( remoteSurface );
1110 tizen_remote_surface_transfer_visibility( remoteSurface, TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE);
1113 void Indicator::UpdateIndicatorImage( Any source )
1115 if( !mNativeImageSource )
1117 mNativeImageSource = Dali::NativeImageSource::New( source );
1118 Dali::NativeImage nativeImage = Dali::NativeImage::New( *mNativeImageSource );
1120 SetForegroundNativeImage( nativeImage );
1121 mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
1122 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
1123 mEventActor.SetSize( mImageWidth, mImageHeight );
1129 mNativeImageSource->SetSource( source );
1130 Dali::Stage::GetCurrent().KeepRendering( 0.0f );
1133 void Indicator::UpdateTopMargin()
1135 int newMargin = (mVisible == Dali::Window::VISIBLE && mOpacityMode == Dali::Window::OPAQUE) ? mImageHeight : 0;
1136 if (mTopMargin != newMargin)
1138 mTopMargin = newMargin;
1139 mAdaptor->IndicatorSizeChanged( mTopMargin );
1143 void Indicator::UpdateVisibility()
1145 if( CheckVisibleState() )
1147 // set default indicator type (enable the quick panel)
1148 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
1152 // set default indicator type (disable the quick panel)
1153 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
1158 mIndicatorContentActor.SetPosition( 0.0f, -mImageHeight, 0.0f );
1161 SetVisible(mVisible, true);
1164 void Indicator::UpdateImageData( int bufferNumber )
1166 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s mVisible: %s", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
1168 if( mState == CONNECTED && mVisible )
1172 // in case of shm indicator (not pixmap), not sure we can skip it when mIsShowing is false
1173 CopyToBuffer( bufferNumber );
1179 mAdaptor->RequestUpdateOnce();
1185 bool Indicator::CopyToBuffer( int bufferNumber )
1187 bool success = false;
1189 if( mSharedFileInfo[bufferNumber].mLock )
1191 Indicator::ScopedLock scopedLock(mSharedFileInfo[bufferNumber].mLock);
1192 if( mSharedFileInfo[bufferNumber].mLock->RetrieveAndClearErrorStatus() )
1196 else if( scopedLock.IsLocked() )
1198 unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
1199 size_t size = mSharedFileInfo[bufferNumber].mImageWidth * mSharedFileInfo[bufferNumber].mImageHeight * 4;
1201 if( mIndicatorBuffer->UpdatePixels( src, size ) )
1203 mAdaptor->RequestUpdateOnce();
1212 void Indicator::LoadPixmapImage( Ecore_Ipc_Event_Server_Data *epcEvent )
1216 void Indicator::CreateNewPixmapImage()
1220 void Indicator::CreateNewImage( int bufferNumber )
1222 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight );
1223 mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight, Pixel::BGRA8888 );
1224 bool success = false;
1226 if( CopyToBuffer( bufferNumber ) ) // Only create images if we have valid image buffer
1228 Dali::Texture texture = Dali::Texture::New( mIndicatorBuffer->GetNativeImage() );
1231 SetForegroundImage( texture );
1238 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
1240 if( mObserver != NULL )
1242 mObserver->IndicatorClosed( this );
1244 // Don't do connection in this callback - strange things happen!
1245 StartReconnectionTimer();
1249 Dali::Geometry Indicator::CreateBackgroundGeometry()
1251 switch( mOpacityMode )
1253 case Dali::Window::TRANSLUCENT:
1254 if( !mTranslucentGeometry )
1256 // Construct 5 interval mesh
1270 struct BackgroundVertex
1276 unsigned int numVertices = 2 * ( NUM_GRADIENT_INTERVALS + 1 );
1277 BackgroundVertex vertices[ numVertices ];
1280 float delta = 1.0f / NUM_GRADIENT_INTERVALS;
1281 BackgroundVertex* currentVertex = vertices;
1282 for( int y = 0; y < NUM_GRADIENT_INTERVALS + 1; ++y, d += delta )
1284 currentVertex->mPosition = Vector2( -0.5f, d );
1285 currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1288 currentVertex->mPosition = Vector2( 0.5f, d );
1289 currentVertex->mAlpha = GRADIENT_ALPHA[ y ];
1294 unsigned int numIndices = 2 * 3 * NUM_GRADIENT_INTERVALS;
1295 unsigned short indices[ numIndices ];
1297 unsigned short* currentIndex = indices;
1298 for( int y = 0; y < NUM_GRADIENT_INTERVALS; ++y )
1300 *currentIndex++ = (2 * y);
1301 *currentIndex++ = (2 * y) + 3;
1302 *currentIndex++ = (2 * y) + 1;
1304 *currentIndex++ = (2 * y);
1305 *currentIndex++ = (2 * y) + 2;
1306 *currentIndex++ = (2 * y) + 3;
1309 Dali::Property::Map vertexFormat;
1310 vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1311 vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1312 Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1313 vertexPropertyBuffer.SetData( vertices, numVertices );
1315 // Create the geometry object
1316 mTranslucentGeometry = Dali::Geometry::New();
1317 mTranslucentGeometry.AddVertexBuffer( vertexPropertyBuffer );
1318 mTranslucentGeometry.SetIndexBuffer( &indices[0], numIndices );
1321 return mTranslucentGeometry;
1322 case Dali::Window::OPAQUE:
1324 if( !mSolidGeometry )
1327 struct BackgroundVertex
1333 BackgroundVertex vertices[ 4 ] = { { Vector2( -0.5f, -0.5f ), 1.0f }, { Vector2( 0.5f, -0.5f ), 1.0f },
1334 { Vector2( -0.5f, 0.5f ), 1.0f }, { Vector2( 0.5f, 0.5f ), 1.0f } };
1337 unsigned short indices[ 6 ] = { 0, 3, 1, 0, 2, 3 };
1339 Dali::Property::Map vertexFormat;
1340 vertexFormat[ "aPosition" ] = Dali::Property::VECTOR2;
1341 vertexFormat[ "aAlpha" ] = Dali::Property::FLOAT;
1342 Dali::PropertyBuffer vertexPropertyBuffer = Dali::PropertyBuffer::New( vertexFormat );
1343 vertexPropertyBuffer.SetData( vertices, 4 );
1346 // Create the geometry object
1347 mSolidGeometry = Dali::Geometry::New();
1348 mSolidGeometry.AddVertexBuffer( vertexPropertyBuffer );
1349 mSolidGeometry.SetIndexBuffer( &indices[0], 6 );
1352 return mSolidGeometry;
1353 case Dali::Window::TRANSPARENT:
1357 return Dali::Geometry();
1360 void Indicator::SetForegroundImage( Dali::Texture texture )
1362 if( !mForegroundRenderer && texture )
1365 Dali::Shader shader = Dali::Shader::New( FOREGROUND_VERTEX_SHADER, FOREGROUND_FRAGMENT_SHADER );
1367 // Create renderer from geometry and material
1368 Dali::Geometry quad = CreateQuadGeometry();
1369 mForegroundRenderer = Dali::Renderer::New( quad, shader );
1370 // Make sure the foreground stays in front of the background
1371 mForegroundRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, 1.f );
1373 // Set blend function
1374 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_RGB, Dali::BlendFactor::ONE );
1375 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_RGB, Dali::BlendFactor::ONE_MINUS_SRC_ALPHA );
1376 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_ALPHA, Dali::BlendFactor::ONE );
1377 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_ALPHA, Dali::BlendFactor::ONE );
1379 // Create a texture-set and add to renderer
1381 Dali::TextureSet textureSet = Dali::TextureSet::New();
1382 textureSet.SetTexture( 0u, texture );
1383 mForegroundRenderer.SetTextures( textureSet );
1385 mIndicatorContentActor.AddRenderer( mForegroundRenderer );
1387 else if( mForegroundRenderer )
1389 Dali::TextureSet textureSet = mForegroundRenderer.GetTextures();
1390 textureSet.SetTexture( 0u, texture );
1393 if( mImageWidth == 0 && mImageHeight == 0 && texture)
1395 Resize( texture.GetWidth(), texture.GetHeight() );
1399 void Indicator::SetForegroundNativeImage( Dali::Image image )
1401 if( !mForegroundRenderer && image )
1404 std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n";
1405 fragmentShader += "\n";
1406 fragmentShader += FOREGROUND_TBM_FRAGMENT_SHADER;
1409 Dali::Shader shader = Dali::Shader::New( FOREGROUND_VERTEX_SHADER, fragmentShader );
1411 // Create renderer from geometry and material
1412 Dali::Geometry quad = CreateQuadGeometry();
1413 mForegroundRenderer = Dali::Renderer::New( quad, shader );
1414 // Make sure the foreground stays in front of the background
1415 mForegroundRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, 1.f );
1417 // Set blend function
1418 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_RGB, Dali::BlendFactor::ONE );
1419 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_RGB, Dali::BlendFactor::ONE_MINUS_SRC_ALPHA );
1420 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_SRC_ALPHA, Dali::BlendFactor::ONE );
1421 mForegroundRenderer.SetProperty( Dali::Renderer::Property::BLEND_FACTOR_DEST_ALPHA, Dali::BlendFactor::ONE );
1423 // Create a texture-set and add to renderer
1425 Dali::TextureSet textureSet = Dali::TextureSet::New();
1426 Dali::TextureSetImage( textureSet, 0u, image );
1428 mForegroundRenderer.SetTextures( textureSet );
1430 mIndicatorContentActor.AddRenderer( mForegroundRenderer );
1432 else if( mForegroundRenderer )
1434 Dali::TextureSet textureSet = mForegroundRenderer.GetTextures();
1435 Dali::TextureSetImage( textureSet, 0u, image );
1438 if( mImageWidth == 0 && mImageHeight == 0 && image )
1440 Resize( image.GetWidth(), image.GetHeight() );
1444 void Indicator::OnIndicatorTypeChanged( Type indicatorType )
1446 if( mObserver != NULL )
1448 mObserver->IndicatorTypeChanged( indicatorType );
1452 void Indicator::DataReceived( void* event )
1454 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1455 Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1457 switch( epcEvent->minor )
1461 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1464 mAdaptor->RequestUpdateOnce();
1468 case OP_UPDATE_DONE:
1470 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
1471 // epcEvent->response == display buffer #
1472 UpdateImageData( epcEvent->response );
1477 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF0\n" );
1478 SetSharedImageInfo( epcEvent );
1483 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF1\n" );
1484 SetLockFileInfo( epcEvent );
1489 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF2\n" );
1490 LoadSharedImage( epcEvent );
1495 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_GL_REF\n" );
1496 SetupNativeIndicatorImage( epcEvent );
1501 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1503 if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1505 IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1506 Resize( newSize->w, newSize->h );
1512 int msgDomain = epcEvent->ref;
1513 int msgId = epcEvent->ref_to;
1515 void *msgData = NULL;
1516 int msgDataSize = 0;
1517 msgData = epcEvent->data;
1518 msgDataSize = epcEvent->size;
1520 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT. msgDomain = %d\n", msgDomain );
1522 if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1526 case MSG_ID_INDICATOR_TYPE:
1528 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1529 Type* indicatorType = static_cast<Type*>( epcEvent->data );
1530 OnIndicatorTypeChanged( *indicatorType );
1534 case MSG_ID_INDICATOR_START_ANIMATION:
1536 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: MSG_ID_INDICATOR_START_ANIMATION\n" );
1538 if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1540 DALI_LOG_ERROR("Message data is incorrect\n");
1544 IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1546 if(!CheckVisibleState())
1548 ShowIndicator( animData->duration /* n sec */ );
1559 void Indicator::ConnectionClosed()
1561 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1563 // Will get this callback if the server connection failed to start up.
1564 delete mServerConnection;
1565 mServerConnection = NULL;
1566 mState = DISCONNECTED;
1568 // Attempt to re-connect
1572 bool Indicator::CheckVisibleState()
1574 if( mOrientation == Dali::Window::LANDSCAPE
1575 || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1576 || (mVisible == Dali::Window::INVISIBLE)
1577 || (mVisible == Dali::Window::AUTO && !mIsShowing) )
1585 void Indicator::ClearSharedFileInfo()
1587 for( int i = 0; i < SHARED_FILE_NUMBER; i++ )
1589 delete mSharedFileInfo[i].mLock;
1590 mSharedFileInfo[i].mLock = NULL;
1592 delete mSharedFileInfo[i].mSharedFile;
1593 mSharedFileInfo[i].mSharedFile = NULL;
1595 mSharedFileInfo[i].mLockFileName.clear();
1596 mSharedFileInfo[i].mSharedFileName.clear();
1601 * duration can be this
1605 * KEEP_SHOWING = -1,
1609 void Indicator::ShowIndicator(float duration)
1611 if( !mIndicatorAnimation )
1613 mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1614 mIndicatorAnimation.FinishedSignal().Connect(this, &Indicator::OnAnimationFinished);
1617 if(mIsShowing && !EqualsZero(duration))
1619 // If need to show during showing, do nothing.
1620 // In 2nd phase (below) will update timer
1622 else if(!mIsShowing && mIsAnimationPlaying && EqualsZero(duration))
1624 // If need to hide during hiding or hidden already, do nothing
1628 mIndicatorAnimation.Clear();
1630 if( EqualsZero(duration) )
1632 mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, -mImageHeight, 0), Dali::AlphaFunction::EASE_OUT );
1636 OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1640 mIndicatorAnimation.AnimateTo( Property( mIndicatorContentActor, Dali::Actor::Property::POSITION ), Vector3(0, 0, 0), Dali::AlphaFunction::EASE_OUT );
1644 OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1647 mIndicatorAnimation.Play();
1648 mIsAnimationPlaying = true;
1655 mShowTimer = Dali::Timer::New(1000 * duration);
1656 mShowTimer.TickSignal().Connect(this, &Indicator::OnShowTimer);
1658 mShowTimer.SetInterval(1000* duration);
1661 if( mVisible == Dali::Window::AUTO )
1663 // check the stage touch
1664 Dali::Stage::GetCurrent().TouchSignal().Connect( this, &Indicator::OnStageTouched );
1669 if(mShowTimer && mShowTimer.IsRunning())
1674 if( mVisible == Dali::Window::AUTO )
1676 // check the stage touch
1677 Dali::Stage::GetCurrent().TouchSignal().Disconnect( this, &Indicator::OnStageTouched );
1682 bool Indicator::OnShowTimer()
1684 // after time up, hide indicator
1685 ShowIndicator( HIDE_NOW );
1690 void Indicator::OnAnimationFinished(Dali::Animation& animation)
1692 mIsAnimationPlaying = false;
1693 // once animation is finished and indicator is hidden, take it off stage
1694 if( mObserver != NULL )
1696 mObserver->IndicatorVisibilityChanged( mIsShowing ); // is showing?
1700 void Indicator::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
1702 // Nothing to do, but we still want to consume pan
1705 void Indicator::OnStageTouched(const Dali::TouchData& touchData)
1707 // when stage is touched while indicator is showing temporary, hide it
1708 if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1710 switch( touchData.GetState( 0 ) )
1712 case Dali::PointState::DOWN:
1714 // if touch point is inside the indicator, indicator is not hidden
1715 if( mImageHeight < int( touchData.GetScreenPosition( 0 ).y ) )
1717 ShowIndicator( HIDE_NOW );