2 * Copyright (c) 2014 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 "indicator-impl.h"
25 #include <sys/types.h>
31 #include <dali/public-api/images/native-image.h>
32 #include <dali/public-api/events/touch-event.h>
33 #include <dali/public-api/events/touch-point.h>
34 #include <dali/public-api/common/stage.h>
35 #include <dali/public-api/actors/blending.h>
36 #include <dali/public-api/shader-effects/shader-effect.h>
38 #include <dali/integration-api/debug.h>
41 #include <adaptor-impl.h>
42 #include <accessibility-adaptor-impl.h>
43 #include <pixmap-image.h>
47 #if defined(DEBUG_ENABLED)
48 #define STATE_DEBUG_STRING(state) (state==DISCONNECTED?"DISCONNECTED":state==CONNECTED?"CONNECTED":"UNKNOWN")
54 const float SLIDING_ANIMATION_DURATION( 0.2f ); // 200 milli seconds
55 const float AUTO_INDICATOR_STAY_DURATION(3.0f); // 3 seconds
56 const float SHOWING_DISTANCE_HEIGHT_RATE(0.34f); // 20 pixels
64 const int NUM_GRADIENT_INTERVALS(5); // Number of gradient intervals
65 const Dali::Vector4 GRADIENT_COLORS[NUM_GRADIENT_INTERVALS+1] =
67 Vector4(0.0f, 0.0f, 0.0f, 0.6f),
68 Vector4(0.0f, 0.0f, 0.0f, 0.38f),
69 Vector4(0.0f, 0.0f, 0.0f, 0.20f),
70 Vector4(0.0f, 0.0f, 0.0f, 0.08f),
71 Vector4(0.0f, 0.0f, 0.0f, 0.0f),
72 Vector4(0.0f, 0.0f, 0.0f, 0.0f),
75 const float OPAQUE_THRESHOLD(0.99f);
76 const float TRANSPARENT_THRESHOLD(0.05f);
78 // indicator service name
79 const char* INDICATOR_SERVICE_NAME("elm_indicator");
81 // Copied from ecore_evas_extn_engine.h
95 OP_PROFILE_CHANGE_REQUEST,
96 OP_PROFILE_CHANGE_DONE,
113 // Copied from elm_conform.c
115 const int MSG_DOMAIN_CONTROL_INDICATOR( 0x10001 );
116 const int MSG_ID_INDICATOR_REPEAT_EVENT( 0x10002 );
117 const int MSG_ID_INDICATOR_ROTATION( 0x10003 );
118 const int MSG_ID_INDICATOR_OPACITY( 0X1004 );
119 const int MSG_ID_INDICATOR_TYPE( 0X1005 );
120 const int MSG_ID_INDICATOR_START_ANIMATION( 0X10006 );
132 struct IpcIndicatorDataAnimation
138 struct IpcDataEvMouseUp
141 Evas_Button_Flags flags;
143 unsigned int timestamp;
144 Evas_Event_Flags event_flags;
146 IpcDataEvMouseUp(unsigned long timestamp)
148 flags(EVAS_BUTTON_NONE),
150 timestamp(static_cast<unsigned int>(timestamp)),
151 event_flags(EVAS_EVENT_FLAG_NONE)
156 struct IpcDataEvMouseDown
159 Evas_Button_Flags flags;
161 unsigned int timestamp;
162 Evas_Event_Flags event_flags;
164 IpcDataEvMouseDown(unsigned long timestamp)
166 flags(EVAS_BUTTON_NONE),
168 timestamp(static_cast<unsigned int>(timestamp)),
169 event_flags(EVAS_EVENT_FLAG_NONE)
174 struct IpcDataEvMouseMove
177 Evas_Button_Flags flags;
179 unsigned int timestamp;
180 Evas_Event_Flags event_flags;
182 IpcDataEvMouseMove(const Dali::TouchPoint& touchPoint, unsigned long timestamp)
183 : x(static_cast<Evas_Coord>(touchPoint.local.x)),
184 y(static_cast<Evas_Coord>(touchPoint.local.y)),
185 flags(EVAS_BUTTON_NONE),
187 timestamp(static_cast<unsigned int>(timestamp)),
188 event_flags(EVAS_EVENT_FLAG_NONE)
193 struct IpcDataEvMouseOut
195 unsigned int timestamp;
197 Evas_Event_Flags event_flags;
199 IpcDataEvMouseOut(unsigned long timestamp)
200 : timestamp(static_cast<unsigned int>(timestamp)),
202 event_flags(EVAS_EVENT_FLAG_NONE)
207 } // anonymous namespace
216 #if defined(DEBUG_ENABLED)
217 Debug::Filter* gIndicatorLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_INDICATOR");
221 Indicator::LockFile::LockFile(const std::string filename)
222 : mFilename(filename),
225 mFileDescriptor = open(filename.c_str(), O_RDWR);
226 if( mFileDescriptor == -1 )
230 DALI_LOG_ERROR( "### Cannot open %s for indicator lock ###\n", mFilename.c_str() );
234 Indicator::LockFile::~LockFile()
236 // Closing file descriptor also unlocks file.
237 close( mFileDescriptor );
240 bool Indicator::LockFile::Lock()
242 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
245 if( mFileDescriptor > 0 )
247 if( lockf( mFileDescriptor, F_LOCK, 0 ) == 0 ) // Note, operation may block.
255 // file descriptor is no longer valid or not writable
258 DALI_LOG_ERROR( "### Cannot lock indicator: bad file descriptor for %s ###\n", mFilename.c_str() );
266 void Indicator::LockFile::Unlock()
268 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
269 if( lockf( mFileDescriptor, F_ULOCK, 0 ) != 0 )
273 // file descriptor is no longer valid or not writable
276 DALI_LOG_ERROR( "### Cannot unlock indicator: bad file descriptor for %s\n", mFilename.c_str() );
281 bool Indicator::LockFile::RetrieveAndClearErrorStatus()
283 bool error = mErrorThrown;
284 mErrorThrown = false;
288 Indicator::ScopedLock::ScopedLock(LockFile* lockFile)
289 : mLockFile(lockFile),
294 mLocked = mLockFile->Lock();
298 Indicator::ScopedLock::~ScopedLock()
306 bool Indicator::ScopedLock::IsLocked()
311 Indicator::Indicator( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, Observer* observer )
313 mGestureDetected( false ),
315 mOpacityMode( Dali::Window::OPAQUE ),
316 mState( DISCONNECTED ),
318 mServerConnection( NULL ),
319 mObserver( observer ),
320 mOrientation( orientation ),
323 mVisible( Dali::Window::INVISIBLE ),
325 mIsAnimationPlaying( false ),
326 mCurrentSharedFile( 0 )
328 mIndicatorImageActor = Dali::ImageActor::New();
329 mIndicatorImageActor.SetBlendFunc( Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE_MINUS_SRC_ALPHA,
330 Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE );
332 mIndicatorImageActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
333 mIndicatorImageActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
335 // Indicator image handles the touch event including "leave"
336 mIndicatorImageActor.SetLeaveRequired( true );
337 mIndicatorImageActor.TouchedSignal().Connect( this, &Indicator::OnTouched );
339 mIndicatorActor = Dali::Actor::New();
340 mIndicatorActor.Add( mIndicatorImageActor );
342 // Event handler to find out flick down gesture
343 mEventActor = Dali::Actor::New();
344 mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
345 mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
346 mEventActor.SetZ( -0.01f );
347 mIndicatorActor.Add( mEventActor );
349 // Attach pan gesture to find flick down during hiding.
350 // It can prevent the problem that scrollview gets pan gesture even indicator area is touched,
351 // since it consumes the pan gesture in advance.
352 mPanDetector = Dali::PanGestureDetector::New();
353 mPanDetector.DetectedSignal().Connect( this, &Indicator::OnPan );
354 mPanDetector.Attach( mEventActor );
358 // register indicator to accessibility adaptor
359 Dali::AccessibilityAdaptor accessibilityAdaptor = AccessibilityAdaptor::Get();
360 if(accessibilityAdaptor)
362 AccessibilityAdaptor::GetImplementation( accessibilityAdaptor ).SetIndicator( this );
364 // hide the indicator by default
365 mIndicatorActor.SetVisible( false );
368 Indicator::~Indicator()
372 mEventActor.TouchedSignal().Disconnect( this, &Indicator::OnTouched );
377 void Indicator::SetAdaptor(Adaptor* adaptor)
380 mIndicatorBuffer->SetAdaptor( adaptor );
383 Dali::Actor Indicator::GetActor()
385 return mIndicatorActor;
388 void Indicator::Open( Dali::Window::WindowOrientation orientation )
390 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
392 // Calls from Window should be set up to ensure we are in a
393 // disconnected state before opening a second time.
394 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
396 mOrientation = orientation;
401 void Indicator::Close()
403 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s", STATE_DEBUG_STRING(mState) );
405 if( mState == CONNECTED )
408 if( mObserver != NULL )
410 mObserver->IndicatorClosed( this );
414 Dali::Image emptyImage;
415 mIndicatorImageActor.SetImage(emptyImage);
418 void Indicator::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
424 void Indicator::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
426 if ( visibleMode != mVisible || forceUpdate )
428 // If we were previously hidden, then we should update the image data before we display the indicator
429 if ( mVisible == Dali::Window::INVISIBLE )
431 UpdateImageData( mCurrentSharedFile );
433 if ( visibleMode != Dali::Window::INVISIBLE )
435 mIndicatorActor.SetVisible( true );
438 mVisible = visibleMode;
440 if( mIndicatorImageActor.GetImage() )
442 if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
445 ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
447 else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
450 ShowIndicator( KEEP_SHOWING );
455 ShowIndicator( HIDE_NOW );
461 bool Indicator::IsConnected()
463 return ( mState == CONNECTED );
466 bool Indicator::SendMessage( int messageDomain, int messageId, const void *data, int size )
470 return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
478 bool Indicator::OnTouched(Dali::Actor indicator, const Dali::TouchEvent& touchEvent)
480 if( mServerConnection )
482 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
484 // Send touch event to indicator server when indicator is showing
485 if( CheckVisibleState() || mIsShowing )
487 switch( touchPoint.state )
489 case Dali::TouchPoint::Down:
491 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
492 IpcDataEvMouseDown ipcDown( touchEvent.time );
493 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
494 mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
496 if( mVisible == Dali::Window::AUTO )
498 // Stop hiding indicator
499 ShowIndicator( KEEP_SHOWING );
504 case Dali::TouchPoint::Motion:
506 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
507 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
511 case Dali::TouchPoint::Up:
513 IpcDataEvMouseUp ipcUp( touchEvent.time );
514 mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
516 if( mVisible == Dali::Window::AUTO )
519 ShowIndicator( 0.5f /* hide after 0.5 sec */ );
524 case Dali::TouchPoint::Leave:
526 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
527 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
528 IpcDataEvMouseUp ipcOut( touchEvent.time );
529 mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
544 bool Indicator::Connect()
546 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
548 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
550 bool connected = false;
552 mServerConnection = new ServerConnection( INDICATOR_SERVICE_NAME, 0, false, this );
553 if( mServerConnection )
555 connected = mServerConnection->IsConnected();
558 delete mServerConnection;
559 mServerConnection = NULL;
565 StartReconnectionTimer();
575 void Indicator::StartReconnectionTimer()
577 if( ! mReconnectTimer )
579 mReconnectTimer = Dali::Timer::New(1000);
580 mConnection.DisconnectAll();
581 mReconnectTimer.TickSignal().Connect( mConnection, &Indicator::OnReconnectTimer );
583 mReconnectTimer.Start();
586 bool Indicator::OnReconnectTimer()
590 if( mState == DISCONNECTED )
601 void Indicator::Disconnect()
603 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
605 mState = DISCONNECTED;
607 delete mServerConnection;
608 mServerConnection = NULL;
610 ClearSharedFileInfo();
613 void Indicator::Resize( int width, int height )
624 if( mImageWidth != width || mImageHeight != height )
627 mImageHeight = height;
629 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
630 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
631 mEventActor.SetSize(mImageWidth, mImageHeight);
637 void Indicator::SetLockFileInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
639 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
641 // epcEvent->ref == w
642 // epcEvent->ref_to == h
643 // epcEvent->response == buffer num
644 // epcEvent->data = lockfile + nul byte
646 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) && (epcEvent->data) &&
647 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
649 int n = epcEvent->response;
651 if( n >= 0 && n < SHARED_FILE_NUMBER )
653 mCurrentSharedFile = n;
655 mSharedFileInfo[n].mImageWidth = epcEvent->ref;
656 mSharedFileInfo[n].mImageHeight = epcEvent->ref_to;
658 mSharedFileInfo[n].mLockFileName.clear();
660 mSharedFileInfo[n].mLockFileName = static_cast< char* >( epcEvent->data );
662 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetLockFileInfo: buffer num = %d, w = %d, h = %d, lock = %s\n",
663 n, mSharedFileInfo[n].mImageWidth, mSharedFileInfo[n].mImageHeight, mSharedFileInfo[n].mLockFileName.c_str() );
668 void Indicator::SetSharedImageInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
670 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
672 // epcEvent->ref == shm id
673 // epcEvent->ref_to == shm num
674 // epcEvent->response == buffer num
675 // epcEvent->data = shm ref string + nul byte
677 if ( (epcEvent->data) &&
678 (epcEvent->size > 0) &&
679 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
681 int n = epcEvent->response;
683 if( n >= 0 && n < SHARED_FILE_NUMBER )
685 mCurrentSharedFile = n;
687 mSharedFileInfo[n].mSharedFileName.clear();
689 mSharedFileInfo[n].mSharedFileName = static_cast< char* >( epcEvent->data );
691 mSharedFileInfo[n].mSharedFileID = epcEvent->ref;
692 mSharedFileInfo[n].mSharedFileNumber = epcEvent->ref_to;
694 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetSharedImageInfo: buffer num %d, shared file = %s, id = %d, num = %d\n",
695 n, mSharedFileInfo[n].mSharedFileName.c_str(), mSharedFileInfo[n].mSharedFileID, mSharedFileInfo[n].mSharedFileNumber );
700 void Indicator::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
702 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
704 // epcEvent->ref == alpha
705 // epcEvent->ref_to == sys
706 // epcEvent->response == buffer num
708 int n = epcEvent->response;
710 if( n >= 0 && n < SHARED_FILE_NUMBER )
712 mCurrentSharedFile = n;
714 delete mSharedFileInfo[n].mSharedFile;
715 mSharedFileInfo[n].mSharedFile = NULL;
717 delete mSharedFileInfo[n].mLock;
718 mSharedFileInfo[n].mLock = NULL;
720 std::stringstream sharedFileID;
721 std::stringstream sharedFileNumber;
723 sharedFileID << mSharedFileInfo[n].mSharedFileID;
724 sharedFileNumber << mSharedFileInfo[n].mSharedFileNumber;
726 std::string sharedFilename = "/" + mSharedFileInfo[n].mSharedFileName + "-" + sharedFileID.str() + "." + sharedFileNumber.str();
728 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "LoadSharedImage: file name = %s\n", sharedFilename.c_str() );
730 mSharedFileInfo[n].mSharedFile = SharedFile::New( sharedFilename.c_str(), mSharedFileInfo[n].mImageWidth * mSharedFileInfo[n].mImageWidth * 4, true );
731 if( mSharedFileInfo[n].mSharedFile != NULL )
733 mSharedFileInfo[n].mLock = new Indicator::LockFile( mSharedFileInfo[n].mLockFileName );
734 if( mSharedFileInfo[n].mLock->RetrieveAndClearErrorStatus() )
736 DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", mSharedFileInfo[n].mLockFileName.c_str() );
741 if( CheckVisibleState() )
743 // set default indicator type (enable the quick panel)
744 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
748 // set default indicator type (disable the quick panel)
749 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
752 SetVisible(mVisible, true);
757 void Indicator::LoadPixmapImage( Ecore_Ipc_Event_Server_Data *epcEvent )
759 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
761 // epcEvent->ref == w
762 // epcEvent->ref_to == h
763 // epcEvent->response == alpha
764 // epcEvent->data = pixmap id
766 if( ( epcEvent->data ) &&
767 (epcEvent->size >= (int)sizeof(PixmapId)) )
769 ClearSharedFileInfo();
771 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
773 mImageWidth = epcEvent->ref;
774 mImageHeight = epcEvent->ref_to;
776 mPixmap = *(static_cast<PixmapId*>(epcEvent->data));
777 CreateNewPixmapImage();
779 if( CheckVisibleState() )
781 // set default indicator type (enable the quick panel)
782 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
786 // set default indicator type (disable the quick panel)
787 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
790 SetVisible(mVisible, true);
795 void Indicator::UpdateImageData( int bufferNumber )
797 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s mVisible: %s", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
799 if( mState == CONNECTED && mVisible )
803 // in case of shm indicator (not pixmap), not sure we can skip it when mIsShowing is false
804 CopyToBuffer( bufferNumber );
810 mAdaptor->RequestUpdateOnce();
816 bool Indicator::CopyToBuffer( int bufferNumber )
818 bool success = false;
820 if( mSharedFileInfo[bufferNumber].mLock )
822 Indicator::ScopedLock scopedLock(mSharedFileInfo[bufferNumber].mLock);
823 if( mSharedFileInfo[bufferNumber].mLock->RetrieveAndClearErrorStatus() )
827 else if( scopedLock.IsLocked() )
829 unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
830 size_t size = mSharedFileInfo[bufferNumber].mImageWidth * mSharedFileInfo[bufferNumber].mImageHeight * 4;
832 if( mIndicatorBuffer->UpdatePixels( src, size ) )
834 mAdaptor->RequestUpdateOnce();
843 void Indicator::SetBackground()
847 void Indicator::CreateNewPixmapImage()
849 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mImageWidth, mImageHeight );
850 Dali::PixmapImagePtr pixmapImage = Dali::PixmapImage::New( mPixmap );
854 mIndicatorImageActor.SetImage( Dali::NativeImage::New(*pixmapImage) );
855 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
856 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
857 mEventActor.SetSize(mImageWidth, mImageHeight);
863 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
865 if( mObserver != NULL )
867 mObserver->IndicatorClosed( this );
869 // Don't do connection in this callback - strange things happen!
870 StartReconnectionTimer();
874 void Indicator::CreateNewImage( int bufferNumber )
876 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight );
877 mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight, Pixel::BGRA8888 );
878 Dali::Image image = Dali::NativeImage::New( mIndicatorBuffer->GetNativeImage() );
880 if( CopyToBuffer( bufferNumber ) ) // Only create images if we have valid image buffer
882 mIndicatorImageActor.SetImage( image );
886 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
888 if( mObserver != NULL )
890 mObserver->IndicatorClosed( this );
892 // Don't do connection in this callback - strange things happen!
893 StartReconnectionTimer();
897 void Indicator::OnIndicatorTypeChanged( Type indicatorType )
899 if( mObserver != NULL )
901 mObserver->IndicatorTypeChanged( indicatorType );
905 void Indicator::DataReceived( void* event )
907 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
908 Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
910 switch( epcEvent->minor )
914 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
915 if( mPixmap != 0 && mIsShowing )
917 mAdaptor->RequestUpdateOnce();
923 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
924 // epcEvent->response == display buffer #
925 UpdateImageData( epcEvent->response );
930 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF0\n" );
931 SetSharedImageInfo( epcEvent );
936 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF1\n" );
937 SetLockFileInfo( epcEvent );
942 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF2\n" );
943 LoadSharedImage( epcEvent );
948 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
950 if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
952 IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
953 Resize( newSize->w, newSize->h );
959 int msgDomain = epcEvent->ref;
960 int msgId = epcEvent->ref_to;
962 void *msgData = NULL;
964 msgData = epcEvent->data;
965 msgDataSize = epcEvent->size;
967 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT. msgDomain = %d\n", msgDomain );
969 if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
973 case MSG_ID_INDICATOR_TYPE:
975 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
976 Type* indicatorType = static_cast<Type*>( epcEvent->data );
977 OnIndicatorTypeChanged( *indicatorType );
981 case MSG_ID_INDICATOR_START_ANIMATION:
983 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: MSG_ID_INDICATOR_START_ANIMATION\n" );
985 if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
987 DALI_LOG_ERROR("Message data is incorrect");
991 IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
993 if(!CheckVisibleState())
995 ShowIndicator( animData->duration /* n sec */ );
1007 void Indicator::ConnectionClosed()
1009 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1011 // Will get this callback if the server connection failed to start up.
1012 delete mServerConnection;
1013 mServerConnection = NULL;
1014 mState = DISCONNECTED;
1016 // Attempt to re-connect
1020 bool Indicator::CheckVisibleState()
1022 if( mOrientation == Dali::Window::LANDSCAPE
1023 || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1024 || (mVisible != Dali::Window::VISIBLE) )
1032 void Indicator::ClearSharedFileInfo()
1034 for( int i = 0; i < SHARED_FILE_NUMBER; i++ )
1036 delete mSharedFileInfo[i].mLock;
1037 mSharedFileInfo[i].mLock = NULL;
1039 delete mSharedFileInfo[i].mSharedFile;
1040 mSharedFileInfo[i].mSharedFile = NULL;
1042 mSharedFileInfo[i].mLockFileName.clear();
1043 mSharedFileInfo[i].mSharedFileName.clear();
1048 * duration can be this
1052 * KEEP_SHOWING = -1,
1056 void Indicator::ShowIndicator(float duration)
1058 if( !mIndicatorAnimation )
1060 mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1061 mIndicatorAnimation.FinishedSignal().Connect(this, &Indicator::OnAnimationFinished);
1064 if(mIsShowing && !EqualsZero(duration))
1066 // If need to show during showing, do nothing.
1067 // In 2nd phase (below) will update timer
1069 else if(!mIsShowing && mIsAnimationPlaying && EqualsZero(duration))
1071 // If need to hide during hiding or hidden already, do nothing
1075 if( EqualsZero(duration) )
1077 mIndicatorAnimation.AnimateTo( Property( mIndicatorImageActor, Dali::Actor::Property::POSITION ), Vector3(0, -mImageHeight, 0), Dali::AlphaFunction::EASE_OUT );
1081 OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1085 mIndicatorAnimation.AnimateTo( Property( mIndicatorImageActor, Dali::Actor::Property::POSITION ), Vector3(0, 0, 0), Dali::AlphaFunction::EASE_OUT );
1089 OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1092 mIndicatorAnimation.Play();
1093 mIsAnimationPlaying = true;
1100 mShowTimer = Dali::Timer::New(1000 * duration);
1101 mShowTimer.TickSignal().Connect(this, &Indicator::OnShowTimer);
1103 mShowTimer.SetInterval(1000* duration);
1106 if( mVisible == Dali::Window::AUTO )
1108 // check the stage touch
1109 Dali::Stage::GetCurrent().TouchedSignal().Connect( this, &Indicator::OnStageTouched );
1114 if(mShowTimer && mShowTimer.IsRunning())
1119 if( mVisible == Dali::Window::AUTO )
1121 // check the stage touch
1122 Dali::Stage::GetCurrent().TouchedSignal().Disconnect( this, &Indicator::OnStageTouched );
1127 bool Indicator::OnShowTimer()
1129 // after time up, hide indicator
1130 ShowIndicator( HIDE_NOW );
1135 void Indicator::OnAnimationFinished(Dali::Animation& animation)
1137 mIsAnimationPlaying = false;
1138 // once animation is finished and indicator is hidden, take it off stage
1141 mIndicatorActor.SetVisible( false );
1143 if( mObserver != NULL )
1145 mObserver->IndicatorVisibilityChanged( mIsShowing ); // is showing?
1150 void Indicator::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
1152 if( mServerConnection )
1154 switch( gesture.state )
1156 case Gesture::Started:
1158 mGestureDetected = false;
1160 // The gesture position is the current position after it has moved by the displacement.
1161 // We want to reference the original position.
1162 mGestureDeltaY = gesture.position.y - gesture.displacement.y;
1165 // No break, Fall through
1166 case Gesture::Continuing:
1168 if( mVisible == Dali::Window::AUTO && !mIsShowing )
1170 // Only take one touch point
1171 if( gesture.numberOfTouches == 1 && mGestureDetected == false )
1173 mGestureDeltaY += gesture.displacement.y;
1175 if( mGestureDeltaY >= mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE )
1177 ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
1178 mGestureDetected = true;
1186 case Gesture::Finished:
1187 case Gesture::Cancelled:
1189 // if indicator is showing, hide again when touching is finished (Since touch leave is activated, checking it in gesture::finish instead of touch::up)
1190 if( mVisible == Dali::Window::AUTO && mIsShowing )
1192 ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
1204 void Indicator::OnStageTouched(const Dali::TouchEvent& touchEvent)
1206 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
1208 // when stage is touched while indicator is showing temporary, hide it
1209 if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1211 switch( touchPoint.state )
1213 case Dali::TouchPoint::Down:
1215 ShowIndicator( HIDE_NOW );