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-manager-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 const char* MESH_VERTEX_SHADER =
82 "attribute lowp vec3 aColor;\n"
83 "varying mediump vec4 vColor;\n"
86 " gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
87 " vColor = vec4(aColor.r, aColor.g, aColor.b, aTexCoord.x);\n"
90 const char* MESH_FRAGMENT_SHADER =
91 "varying mediump vec4 vColor;\n"
94 " gl_FragColor = vColor*uColor;\n"
97 // Copied from ecore_evas_extn_engine.h
111 OP_PROFILE_CHANGE_REQUEST,
112 OP_PROFILE_CHANGE_DONE,
129 // Copied from elm_conform.c
131 const int MSG_DOMAIN_CONTROL_INDICATOR( 0x10001 );
132 const int MSG_ID_INDICATOR_REPEAT_EVENT( 0x10002 );
133 const int MSG_ID_INDICATOR_ROTATION( 0x10003 );
134 const int MSG_ID_INDICATOR_OPACITY( 0X1004 );
135 const int MSG_ID_INDICATOR_TYPE( 0X1005 );
136 const int MSG_ID_INDICATOR_START_ANIMATION( 0X10006 );
148 struct IpcIndicatorDataAnimation
154 struct IpcDataEvMouseUp
157 Evas_Button_Flags flags;
159 unsigned int timestamp;
160 Evas_Event_Flags event_flags;
162 IpcDataEvMouseUp(unsigned long timestamp)
164 flags(EVAS_BUTTON_NONE),
166 timestamp(static_cast<unsigned int>(timestamp)),
167 event_flags(EVAS_EVENT_FLAG_NONE)
172 struct IpcDataEvMouseDown
175 Evas_Button_Flags flags;
177 unsigned int timestamp;
178 Evas_Event_Flags event_flags;
180 IpcDataEvMouseDown(unsigned long timestamp)
182 flags(EVAS_BUTTON_NONE),
184 timestamp(static_cast<unsigned int>(timestamp)),
185 event_flags(EVAS_EVENT_FLAG_NONE)
190 struct IpcDataEvMouseMove
193 Evas_Button_Flags flags;
195 unsigned int timestamp;
196 Evas_Event_Flags event_flags;
198 IpcDataEvMouseMove(const Dali::TouchPoint& touchPoint, unsigned long timestamp)
199 : x(static_cast<Evas_Coord>(touchPoint.local.x)),
200 y(static_cast<Evas_Coord>(touchPoint.local.y)),
201 flags(EVAS_BUTTON_NONE),
203 timestamp(static_cast<unsigned int>(timestamp)),
204 event_flags(EVAS_EVENT_FLAG_NONE)
209 struct IpcDataEvMouseOut
211 unsigned int timestamp;
213 Evas_Event_Flags event_flags;
215 IpcDataEvMouseOut(unsigned long timestamp)
216 : timestamp(static_cast<unsigned int>(timestamp)),
218 event_flags(EVAS_EVENT_FLAG_NONE)
223 void SetMeshDataColors(Dali::AnimatableMesh mesh, const Vector4 (&colors)[NUM_GRADIENT_INTERVALS+1])
225 for( size_t i=0; i<NUM_GRADIENT_INTERVALS+1; i++ )
228 mesh[j].SetColor(colors[i]);
229 mesh[j+1].SetColor(colors[i]);
230 mesh[j].SetTextureCoords(Dali::Vector2(colors[i].a, colors[i].a));
231 mesh[j+1].SetTextureCoords(Dali::Vector2(colors[i].a, colors[i].a));
235 void SetMeshDataColors(Dali::AnimatableMesh mesh, const Vector4& color)
237 for( size_t i=0, length=NUM_GRADIENT_INTERVALS+1 ; i<length; i++ )
240 mesh[j].SetColor(color);
241 mesh[j+1].SetColor(color);
242 mesh[j].SetTextureCoords(Dali::Vector2(color.a, color.a));
243 mesh[j+1].SetTextureCoords(Dali::Vector2(color.a, color.a));
247 } // anonymous namespace
256 #if defined(DEBUG_ENABLED)
257 Debug::Filter* gIndicatorLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_INDICATOR");
261 Indicator::LockFile::LockFile(const std::string filename)
262 : mFilename(filename),
265 mFileDescriptor = open(filename.c_str(), O_RDWR);
266 if( mFileDescriptor == -1 )
270 DALI_LOG_ERROR( "### Cannot open %s for indicator lock ###\n", mFilename.c_str() );
274 Indicator::LockFile::~LockFile()
276 // Closing file descriptor also unlocks file.
277 close( mFileDescriptor );
280 bool Indicator::LockFile::Lock()
282 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
285 if( mFileDescriptor > 0 )
287 if( lockf( mFileDescriptor, F_LOCK, 0 ) == 0 ) // Note, operation may block.
295 // file descriptor is no longer valid or not writable
298 DALI_LOG_ERROR( "### Cannot lock indicator: bad file descriptor for %s ###\n", mFilename.c_str() );
306 void Indicator::LockFile::Unlock()
308 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
309 if( lockf( mFileDescriptor, F_ULOCK, 0 ) != 0 )
313 // file descriptor is no longer valid or not writable
316 DALI_LOG_ERROR( "### Cannot unlock indicator: bad file descriptor for %s\n", mFilename.c_str() );
321 bool Indicator::LockFile::RetrieveAndClearErrorStatus()
323 bool error = mErrorThrown;
324 mErrorThrown = false;
328 Indicator::ScopedLock::ScopedLock(LockFile* lockFile)
329 : mLockFile(lockFile),
334 mLocked = mLockFile->Lock();
338 Indicator::ScopedLock::~ScopedLock()
346 bool Indicator::ScopedLock::IsLocked()
351 Indicator::Indicator( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, Observer* observer )
353 mGestureDetected( false ),
355 mOpacityMode( Dali::Window::OPAQUE ),
356 mState( DISCONNECTED ),
358 mServerConnection( NULL ),
359 mObserver( observer ),
360 mOrientation( orientation ),
363 mVisible( Dali::Window::INVISIBLE ),
365 mIsAnimationPlaying( false ),
366 mCurrentSharedFile( 0 )
368 mIndicatorImageActor = Dali::ImageActor::New();
369 mIndicatorImageActor.SetBlendFunc( Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE_MINUS_SRC_ALPHA,
370 Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE );
372 mIndicatorImageActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
373 mIndicatorImageActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
375 // Indicator image handles the touch event including "leave"
376 mIndicatorImageActor.SetLeaveRequired( true );
377 mIndicatorImageActor.TouchedSignal().Connect( this, &Indicator::OnTouched );
380 mBackgroundActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
381 mBackgroundActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
382 mBackgroundActor.SetZ( -0.02f );
384 // add background to image actor to move it with indicator image
385 mIndicatorImageActor.Add( mBackgroundActor );
387 mIndicatorActor = Dali::Actor::New();
388 mIndicatorActor.Add( mIndicatorImageActor );
390 if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE )
392 mBackgroundActor.SetVisible( false );
395 // Event handler to find out flick down gesture
396 mEventActor = Dali::Actor::New();
397 mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
398 mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
399 mEventActor.SetZ( -0.01f );
400 mIndicatorActor.Add( mEventActor );
402 // Attach pan gesture to find flick down during hiding.
403 // It can prevent the problem that scrollview gets pan gesture even indicator area is touched,
404 // since it consumes the pan gesture in advance.
405 mPanDetector = Dali::PanGestureDetector::New();
406 mPanDetector.DetectedSignal().Connect( this, &Indicator::OnPan );
407 mPanDetector.Attach( mEventActor );
411 // register indicator to accessibility manager
412 Dali::AccessibilityManager accessibilityManager = AccessibilityManager::Get();
413 if(accessibilityManager)
415 AccessibilityManager::GetImplementation( accessibilityManager ).SetIndicator( this );
417 // hide the indicator by default
418 mIndicatorActor.SetVisible( false );
421 Indicator::~Indicator()
425 mEventActor.TouchedSignal().Disconnect( this, &Indicator::OnTouched );
430 void Indicator::SetAdaptor(Adaptor* adaptor)
433 mIndicatorBuffer->SetAdaptor( adaptor );
436 Dali::Actor Indicator::GetActor()
438 return mIndicatorActor;
441 void Indicator::Open( Dali::Window::WindowOrientation orientation )
443 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
445 // Calls from Window should be set up to ensure we are in a
446 // disconnected state before opening a second time.
447 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
449 mOrientation = orientation;
453 // Change background visibility depending on orientation
454 if(mOrientation == Dali::Window::PORTRAIT || mOrientation == Dali::Window::PORTRAIT_INVERSE)
456 mBackgroundActor.SetVisible(true);
460 mBackgroundActor.SetVisible(false);
464 void Indicator::Close()
466 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s", STATE_DEBUG_STRING(mState) );
468 if( mState == CONNECTED )
471 if( mObserver != NULL )
473 mObserver->IndicatorClosed( this );
477 Dali::Image emptyImage;
478 mIndicatorImageActor.SetImage(emptyImage);
481 void Indicator::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
487 void Indicator::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
489 if ( visibleMode != mVisible || forceUpdate )
491 // If we were previously hidden, then we should update the image data before we display the indicator
492 if ( mVisible == Dali::Window::INVISIBLE )
494 UpdateImageData( mCurrentSharedFile );
496 if ( visibleMode != Dali::Window::INVISIBLE )
498 mIndicatorActor.SetVisible( true );
501 mVisible = visibleMode;
503 if( mIndicatorImageActor.GetImage() )
505 if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
508 ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
510 else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
513 ShowIndicator( KEEP_SHOWING );
518 ShowIndicator( HIDE_NOW );
524 bool Indicator::IsConnected()
526 return ( mState == CONNECTED );
529 bool Indicator::SendMessage( int messageDomain, int messageId, const void *data, int size )
533 return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
541 bool Indicator::OnTouched(Dali::Actor indicator, const Dali::TouchEvent& touchEvent)
543 if( mServerConnection )
545 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
547 // Send touch event to indicator server when indicator is showing
548 if( CheckVisibleState() || mIsShowing )
550 switch( touchPoint.state )
552 case Dali::TouchPoint::Down:
554 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
555 IpcDataEvMouseDown ipcDown( touchEvent.time );
556 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
557 mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
559 if( mVisible == Dali::Window::AUTO )
561 // Stop hiding indicator
562 ShowIndicator( KEEP_SHOWING );
567 case Dali::TouchPoint::Motion:
569 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
570 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
574 case Dali::TouchPoint::Up:
576 IpcDataEvMouseUp ipcUp( touchEvent.time );
577 mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
579 if( mVisible == Dali::Window::AUTO )
582 ShowIndicator( 0.5f /* hide after 0.5 sec */ );
587 case Dali::TouchPoint::Leave:
589 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
590 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
591 IpcDataEvMouseUp ipcOut( touchEvent.time );
592 mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
607 bool Indicator::Connect()
609 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
611 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
613 bool connected = false;
615 mServerConnection = new ServerConnection( INDICATOR_SERVICE_NAME, 0, false, this );
616 if( mServerConnection )
618 connected = mServerConnection->IsConnected();
621 delete mServerConnection;
622 mServerConnection = NULL;
628 StartReconnectionTimer();
638 void Indicator::StartReconnectionTimer()
640 if( ! mReconnectTimer )
642 mReconnectTimer = Dali::Timer::New(1000);
643 mConnection.DisconnectAll();
644 mReconnectTimer.TickSignal().Connect( mConnection, &Indicator::OnReconnectTimer );
646 mReconnectTimer.Start();
649 bool Indicator::OnReconnectTimer()
653 if( mState == DISCONNECTED )
664 void Indicator::Disconnect()
666 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
668 mState = DISCONNECTED;
670 delete mServerConnection;
671 mServerConnection = NULL;
673 ClearSharedFileInfo();
676 void Indicator::Resize( int width, int height )
687 if( mImageWidth != width || mImageHeight != height )
690 mImageHeight = height;
692 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
693 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
694 mEventActor.SetSize(mImageWidth, mImageHeight);
697 if( mBackgroundActor )
699 mBackgroundActor.SetSize( mImageWidth, mImageHeight );
704 void Indicator::SetLockFileInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
706 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
708 // epcEvent->ref == w
709 // epcEvent->ref_to == h
710 // epcEvent->response == buffer num
711 // epcEvent->data = lockfile + nul byte
713 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) && (epcEvent->data) &&
714 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
716 int n = epcEvent->response;
718 if( n >= 0 && n < SHARED_FILE_NUMBER )
720 mCurrentSharedFile = n;
722 mSharedFileInfo[n].mImageWidth = epcEvent->ref;
723 mSharedFileInfo[n].mImageHeight = epcEvent->ref_to;
725 mSharedFileInfo[n].mLockFileName.clear();
727 mSharedFileInfo[n].mLockFileName = static_cast< char* >( epcEvent->data );
729 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetLockFileInfo: buffer num = %d, w = %d, h = %d, lock = %s\n",
730 n, mSharedFileInfo[n].mImageWidth, mSharedFileInfo[n].mImageHeight, mSharedFileInfo[n].mLockFileName.c_str() );
735 void Indicator::SetSharedImageInfo( Ecore_Ipc_Event_Server_Data *epcEvent )
737 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
739 // epcEvent->ref == shm id
740 // epcEvent->ref_to == shm num
741 // epcEvent->response == buffer num
742 // epcEvent->data = shm ref string + nul byte
744 if ( (epcEvent->data) &&
745 (epcEvent->size > 0) &&
746 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
748 int n = epcEvent->response;
750 if( n >= 0 && n < SHARED_FILE_NUMBER )
752 mCurrentSharedFile = n;
754 mSharedFileInfo[n].mSharedFileName.clear();
756 mSharedFileInfo[n].mSharedFileName = static_cast< char* >( epcEvent->data );
758 mSharedFileInfo[n].mSharedFileID = epcEvent->ref;
759 mSharedFileInfo[n].mSharedFileNumber = epcEvent->ref_to;
761 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "SetSharedImageInfo: buffer num %d, shared file = %s, id = %d, num = %d\n",
762 n, mSharedFileInfo[n].mSharedFileName.c_str(), mSharedFileInfo[n].mSharedFileID, mSharedFileInfo[n].mSharedFileNumber );
767 void Indicator::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
769 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
771 // epcEvent->ref == alpha
772 // epcEvent->ref_to == sys
773 // epcEvent->response == buffer num
775 int n = epcEvent->response;
777 if( n >= 0 && n < SHARED_FILE_NUMBER )
779 mCurrentSharedFile = n;
781 delete mSharedFileInfo[n].mSharedFile;
782 mSharedFileInfo[n].mSharedFile = NULL;
784 delete mSharedFileInfo[n].mLock;
785 mSharedFileInfo[n].mLock = NULL;
787 std::stringstream sharedFileID;
788 std::stringstream sharedFileNumber;
790 sharedFileID << mSharedFileInfo[n].mSharedFileID;
791 sharedFileNumber << mSharedFileInfo[n].mSharedFileNumber;
793 std::string sharedFilename = "/" + mSharedFileInfo[n].mSharedFileName + "-" + sharedFileID.str() + "." + sharedFileNumber.str();
795 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "LoadSharedImage: file name = %s\n", sharedFilename.c_str() );
797 mSharedFileInfo[n].mSharedFile = SharedFile::New( sharedFilename.c_str(), mSharedFileInfo[n].mImageWidth * mSharedFileInfo[n].mImageWidth * 4, true );
798 if( mSharedFileInfo[n].mSharedFile != NULL )
800 mSharedFileInfo[n].mLock = new Indicator::LockFile( mSharedFileInfo[n].mLockFileName );
801 if( mSharedFileInfo[n].mLock->RetrieveAndClearErrorStatus() )
803 DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", mSharedFileInfo[n].mLockFileName.c_str() );
808 if( CheckVisibleState() )
810 // set default indicator type (enable the quick panel)
811 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
815 // set default indicator type (disable the quick panel)
816 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
819 SetVisible(mVisible, true);
824 void Indicator::LoadPixmapImage( Ecore_Ipc_Event_Server_Data *epcEvent )
826 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
828 // epcEvent->ref == w
829 // epcEvent->ref_to == h
830 // epcEvent->response == alpha
831 // epcEvent->data = pixmap id
833 if( ( epcEvent->data ) &&
834 (epcEvent->size >= (int)sizeof(PixmapId)) )
836 ClearSharedFileInfo();
838 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
840 mImageWidth = epcEvent->ref;
841 mImageHeight = epcEvent->ref_to;
843 mPixmap = *(static_cast<PixmapId*>(epcEvent->data));
844 CreateNewPixmapImage();
846 if( CheckVisibleState() )
848 // set default indicator type (enable the quick panel)
849 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
853 // set default indicator type (disable the quick panel)
854 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
857 SetVisible(mVisible, true);
862 void Indicator::UpdateImageData( int bufferNumber )
864 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s mVisible: %s", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
866 if( mState == CONNECTED && mVisible )
870 // in case of shm indicator (not pixmap), not sure we can skip it when mIsShowing is false
871 CopyToBuffer( bufferNumber );
877 mAdaptor->RequestUpdateOnce();
883 bool Indicator::CopyToBuffer( int bufferNumber )
885 bool success = false;
887 if( mSharedFileInfo[bufferNumber].mLock )
889 Indicator::ScopedLock scopedLock(mSharedFileInfo[bufferNumber].mLock);
890 if( mSharedFileInfo[bufferNumber].mLock->RetrieveAndClearErrorStatus() )
894 else if( scopedLock.IsLocked() )
896 unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
897 size_t size = mSharedFileInfo[bufferNumber].mImageWidth * mSharedFileInfo[bufferNumber].mImageHeight * 4;
899 if( mIndicatorBuffer->UpdatePixels( src, size ) )
901 mAdaptor->RequestUpdateOnce();
910 void Indicator::SetBackground()
912 if( ! mBackgroundActor )
914 ConstructBackgroundMesh();
917 switch( mOpacityMode )
919 case Dali::Window::TRANSLUCENT:
921 SetMeshDataColors( mBackgroundMesh, GRADIENT_COLORS );
925 case Dali::Window::TRANSPARENT:
927 SetMeshDataColors( mBackgroundMesh, Color::TRANSPARENT );
931 case Dali::Window::OPAQUE:
934 SetMeshDataColors( mBackgroundMesh, Color::BLACK );
940 void Indicator::CreateNewPixmapImage()
942 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mImageWidth, mImageHeight );
943 Dali::PixmapImagePtr pixmapImage = Dali::PixmapImage::New( mPixmap );
947 mIndicatorImageActor.SetImage( Dali::NativeImage::New(*pixmapImage) );
948 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
949 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
950 mEventActor.SetSize(mImageWidth, mImageHeight);
953 if( mBackgroundActor )
955 mBackgroundActor.SetSize( mImageWidth, mImageHeight );
960 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
962 if( mObserver != NULL )
964 mObserver->IndicatorClosed( this );
966 // Don't do connection in this callback - strange things happen!
967 StartReconnectionTimer();
971 void Indicator::CreateNewImage( int bufferNumber )
973 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight );
974 mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mSharedFileInfo[bufferNumber].mImageWidth, mSharedFileInfo[bufferNumber].mImageHeight, Pixel::BGRA8888 );
975 Dali::Image image = Dali::NativeImage::New( mIndicatorBuffer->GetNativeImage() );
977 if( CopyToBuffer( bufferNumber ) ) // Only create images if we have valid image buffer
979 mIndicatorImageActor.SetImage( image );
983 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
985 if( mObserver != NULL )
987 mObserver->IndicatorClosed( this );
989 // Don't do connection in this callback - strange things happen!
990 StartReconnectionTimer();
994 void Indicator::OnIndicatorTypeChanged( Type indicatorType )
996 if( mObserver != NULL )
998 mObserver->IndicatorTypeChanged( indicatorType );
1002 void Indicator::DataReceived( void* event )
1004 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1005 Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1007 switch( epcEvent->minor )
1011 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1012 if( mPixmap != 0 && mIsShowing )
1014 mAdaptor->RequestUpdateOnce();
1018 case OP_UPDATE_DONE:
1020 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
1021 // epcEvent->response == display buffer #
1022 UpdateImageData( epcEvent->response );
1027 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF0\n" );
1028 SetSharedImageInfo( epcEvent );
1033 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF1\n" );
1034 SetLockFileInfo( epcEvent );
1039 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF2\n" );
1040 LoadSharedImage( epcEvent );
1045 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1047 if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1049 IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1050 Resize( newSize->w, newSize->h );
1056 int msgDomain = epcEvent->ref;
1057 int msgId = epcEvent->ref_to;
1059 void *msgData = NULL;
1060 int msgDataSize = 0;
1061 msgData = epcEvent->data;
1062 msgDataSize = epcEvent->size;
1064 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT. msgDomain = %d\n", msgDomain );
1066 if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1070 case MSG_ID_INDICATOR_TYPE:
1072 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1073 Type* indicatorType = static_cast<Type*>( epcEvent->data );
1074 OnIndicatorTypeChanged( *indicatorType );
1078 case MSG_ID_INDICATOR_START_ANIMATION:
1080 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: MSG_ID_INDICATOR_START_ANIMATION\n" );
1082 if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1084 DALI_LOG_ERROR("Message data is incorrect");
1088 IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1090 if(!CheckVisibleState())
1092 ShowIndicator( animData->duration /* n sec */ );
1104 void Indicator::ConnectionClosed()
1106 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1108 // Will get this callback if the server connection failed to start up.
1109 delete mServerConnection;
1110 mServerConnection = NULL;
1111 mState = DISCONNECTED;
1113 // Attempt to re-connect
1117 bool Indicator::CheckVisibleState()
1119 if( mOrientation == Dali::Window::LANDSCAPE
1120 || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1121 || (mVisible != Dali::Window::VISIBLE) )
1129 void Indicator::ConstructBackgroundMesh()
1131 // Construct 5 interval mesh
1143 Dali::AnimatableMesh::Faces faces;
1144 faces.reserve(NUM_GRADIENT_INTERVALS * 6); // 2 tris per interval
1145 for(int i=0; i<NUM_GRADIENT_INTERVALS; i++)
1148 faces.push_back(j); faces.push_back(j+3); faces.push_back(j+1);
1149 faces.push_back(j); faces.push_back(j+2); faces.push_back(j+3);
1152 mBackgroundMesh = Dali::AnimatableMesh::New((NUM_GRADIENT_INTERVALS+1)*2, faces);
1153 float interval=1.0f / (float)NUM_GRADIENT_INTERVALS;
1154 for(int i=0;i<NUM_GRADIENT_INTERVALS+1;i++)
1157 mBackgroundMesh[j ].SetPosition(Vector3(-0.5f, -0.5f+(interval*(float)i), 0.0f));
1158 mBackgroundMesh[j+1].SetPosition(Vector3( 0.5f, -0.5f+(interval*(float)i), 0.0f));
1161 mBackgroundActor = Dali::MeshActor::New(mBackgroundMesh);
1162 Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( MESH_VERTEX_SHADER, MESH_FRAGMENT_SHADER,
1163 GEOMETRY_TYPE_UNTEXTURED_MESH, // Using vertex color
1164 Dali::ShaderEffect::HINT_BLENDING );
1165 mBackgroundActor.SetShaderEffect(shaderEffect);
1168 void Indicator::ClearSharedFileInfo()
1170 for( int i = 0; i < SHARED_FILE_NUMBER; i++ )
1172 delete mSharedFileInfo[i].mLock;
1173 mSharedFileInfo[i].mLock = NULL;
1175 delete mSharedFileInfo[i].mSharedFile;
1176 mSharedFileInfo[i].mSharedFile = NULL;
1178 mSharedFileInfo[i].mLockFileName.clear();
1179 mSharedFileInfo[i].mSharedFileName.clear();
1184 * duration can be this
1188 * KEEP_SHOWING = -1,
1192 void Indicator::ShowIndicator(float duration)
1194 if( !mIndicatorAnimation )
1196 mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1197 mIndicatorAnimation.FinishedSignal().Connect(this, &Indicator::OnAnimationFinished);
1200 if(mIsShowing && !EqualsZero(duration))
1202 // If need to show during showing, do nothing.
1203 // In 2nd phase (below) will update timer
1205 else if(!mIsShowing && mIsAnimationPlaying && EqualsZero(duration))
1207 // If need to hide during hiding or hidden already, do nothing
1211 if( EqualsZero(duration) )
1213 mIndicatorAnimation.AnimateTo( Property( mIndicatorImageActor, Dali::Actor::Property::POSITION ), Vector3(0, -mImageHeight, 0), Dali::AlphaFunction::EASE_OUT );
1217 OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1221 mIndicatorAnimation.AnimateTo( Property( mIndicatorImageActor, Dali::Actor::Property::POSITION ), Vector3(0, 0, 0), Dali::AlphaFunction::EASE_OUT );
1225 OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1228 mIndicatorAnimation.Play();
1229 mIsAnimationPlaying = true;
1236 mShowTimer = Dali::Timer::New(1000 * duration);
1237 mShowTimer.TickSignal().Connect(this, &Indicator::OnShowTimer);
1239 mShowTimer.SetInterval(1000* duration);
1242 if( mVisible == Dali::Window::AUTO )
1244 // check the stage touch
1245 Dali::Stage::GetCurrent().TouchedSignal().Connect( this, &Indicator::OnStageTouched );
1250 if(mShowTimer && mShowTimer.IsRunning())
1255 if( mVisible == Dali::Window::AUTO )
1257 // check the stage touch
1258 Dali::Stage::GetCurrent().TouchedSignal().Disconnect( this, &Indicator::OnStageTouched );
1263 bool Indicator::OnShowTimer()
1265 // after time up, hide indicator
1266 ShowIndicator( HIDE_NOW );
1271 void Indicator::OnAnimationFinished(Dali::Animation& animation)
1273 mIsAnimationPlaying = false;
1274 // once animation is finished and indicator is hidden, take it off stage
1277 mIndicatorActor.SetVisible( false );
1279 if( mObserver != NULL )
1281 mObserver->IndicatorVisibilityChanged( mIsShowing ); // is showing?
1286 void Indicator::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
1288 if( mServerConnection )
1290 switch( gesture.state )
1292 case Gesture::Started:
1294 mGestureDetected = false;
1296 // The gesture position is the current position after it has moved by the displacement.
1297 // We want to reference the original position.
1298 mGestureDeltaY = gesture.position.y - gesture.displacement.y;
1301 // No break, Fall through
1302 case Gesture::Continuing:
1304 if( mVisible == Dali::Window::AUTO && !mIsShowing )
1306 // Only take one touch point
1307 if( gesture.numberOfTouches == 1 && mGestureDetected == false )
1309 mGestureDeltaY += gesture.displacement.y;
1311 if( mGestureDeltaY >= mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE )
1313 ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
1314 mGestureDetected = true;
1322 case Gesture::Finished:
1323 case Gesture::Cancelled:
1325 // if indicator is showing, hide again when touching is finished (Since touch leave is activated, checking it in gesture::finish instead of touch::up)
1326 if( mVisible == Dali::Window::AUTO && mIsShowing )
1328 ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
1340 void Indicator::OnStageTouched(const Dali::TouchEvent& touchEvent)
1342 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
1344 // when stage is touched while indicator is showing temporary, hide it
1345 if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1347 switch( touchPoint.state )
1349 case Dali::TouchPoint::Down:
1351 ShowIndicator( HIDE_NOW );