2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include "indicator-impl.h"
24 #include <sys/types.h>
30 #include <dali/public-api/images/bitmap-image.h>
31 #include <dali/public-api/adaptor-framework/common/pixmap-image.h>
32 #include <dali/public-api/actors/image-actor.h>
33 #include <dali/public-api/events/touch-event.h>
34 #include <dali/public-api/events/touch-point.h>
35 #include <dali/public-api/common/stage.h>
36 #include <dali/public-api/actors/blending.h>
37 #include <dali/public-api/shader-effects/shader-effect.h>
39 #include <dali/integration-api/debug.h>
42 #include <internal/common/adaptor-impl.h>
43 #include <internal/common/accessibility-manager-impl.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.33f);
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 orientation
79 const char* ELM_INDICATOR_PORTRAIT("elm_indicator_portrait");
80 const char* ELM_INDICATOR_LANDSCAPE("elm_indicator_landscape");
82 const char* MESH_VERTEX_SHADER =
83 "attribute lowp vec3 aColor;\n"
84 "varying mediump vec4 vColor;\n"
87 " gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
88 " vColor = vec4(aColor.r, aColor.g, aColor.b, aTexCoord.x);\n"
91 const char* MESH_FRAGMENT_SHADER =
92 "varying mediump vec4 vColor;\n"
95 " gl_FragColor = vColor*uColor;\n"
98 // Copied from elm_win.h
101 * Defines the type modes of indicator that can be shown
102 * If the indicator can support several type of indicator,
103 * you can use this enum value to deal with different type of indicator
107 ELM_WIN_INDICATOR_TYPE_UNKNOWN, /**< Unknown indicator type mode */
108 ELM_WIN_INDICATOR_TYPE_1, /**< Type 0 the the indicator */
109 ELM_WIN_INDICATOR_TYPE_2, /**< Type 1 the indicator */
110 } Elm_Win_Indicator_Type_Mode;
112 // Copied from ecore_evas_extn.c
142 // Copied from elm_conform.c
144 const int MSG_DOMAIN_CONTROL_INDICATOR(0x10001);
145 const int MSG_ID_INDICATOR_REPEAT_EVENT(0x10002);
146 const int MSG_ID_INDICATOR_ROTATION(0x10003);
147 const int MSG_ID_INDICATOR_OPACITY(0X1004);
148 const int MSG_ID_INDICATOR_TYPE(0X1005);
149 const int MSG_ID_INDICATOR_START_ANIMATION(0X10006);
161 struct IpcIndicatorDataAnimation
167 struct IpcDataEvMouseUp
170 Evas_Button_Flags flags;
172 unsigned int timestamp;
173 Evas_Event_Flags event_flags;
175 IpcDataEvMouseUp(unsigned long timestamp)
177 flags(EVAS_BUTTON_NONE),
179 timestamp(static_cast<unsigned int>(timestamp)),
180 event_flags(EVAS_EVENT_FLAG_NONE)
185 struct IpcDataEvMouseDown
188 Evas_Button_Flags flags;
190 unsigned int timestamp;
191 Evas_Event_Flags event_flags;
193 IpcDataEvMouseDown(unsigned long timestamp)
195 flags(EVAS_BUTTON_NONE),
197 timestamp(static_cast<unsigned int>(timestamp)),
198 event_flags(EVAS_EVENT_FLAG_NONE)
203 struct IpcDataEvMouseMove
206 Evas_Button_Flags flags;
208 unsigned int timestamp;
209 Evas_Event_Flags event_flags;
211 IpcDataEvMouseMove(const Dali::TouchPoint& touchPoint, unsigned long timestamp)
212 : x(static_cast<Evas_Coord>(touchPoint.local.x)),
213 y(static_cast<Evas_Coord>(touchPoint.local.y)),
214 flags(EVAS_BUTTON_NONE),
216 timestamp(static_cast<unsigned int>(timestamp)),
217 event_flags(EVAS_EVENT_FLAG_NONE)
222 struct IpcDataEvMouseOut
224 unsigned int timestamp;
226 Evas_Event_Flags event_flags;
228 IpcDataEvMouseOut(unsigned long timestamp)
229 : timestamp(static_cast<unsigned int>(timestamp)),
231 event_flags(EVAS_EVENT_FLAG_NONE)
236 void SetMeshDataColors(Dali::AnimatableMesh mesh, const Vector4 (&colors)[NUM_GRADIENT_INTERVALS+1])
238 for( size_t i=0; i<NUM_GRADIENT_INTERVALS+1; i++ )
241 mesh[j].SetColor(colors[i]);
242 mesh[j+1].SetColor(colors[i]);
243 mesh[j].SetTextureCoords(Dali::Vector2(colors[i].a, colors[i].a));
244 mesh[j+1].SetTextureCoords(Dali::Vector2(colors[i].a, colors[i].a));
248 void SetMeshDataColors(Dali::AnimatableMesh mesh, const Vector4& color)
250 for( size_t i=0, length=NUM_GRADIENT_INTERVALS+1 ; i<length; i++ )
253 mesh[j].SetColor(color);
254 mesh[j+1].SetColor(color);
255 mesh[j].SetTextureCoords(Dali::Vector2(color.a, color.a));
256 mesh[j+1].SetTextureCoords(Dali::Vector2(color.a, color.a));
260 } // anonymous namespace
269 #if defined(DEBUG_ENABLED)
270 Debug::Filter* gIndicatorLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_INDICATOR");
274 Indicator::LockFile::LockFile(const char* filename)
275 : mFilename(filename),
278 mFileDescriptor = open(filename, O_RDWR);
279 if( mFileDescriptor == -1 )
283 DALI_LOG_ERROR( "### Cannot open %s for indicator lock ###\n", mFilename.c_str() );
287 Indicator::LockFile::~LockFile()
289 // Closing file descriptor also unlocks file.
290 close( mFileDescriptor );
293 bool Indicator::LockFile::Lock()
295 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
298 if( mFileDescriptor > 0 )
300 if( lockf( mFileDescriptor, F_LOCK, 0 ) == 0 ) // Note, operation may block.
308 // file descriptor is no longer valid or not writable
311 DALI_LOG_ERROR( "### Cannot lock indicator: bad file descriptor for %s ###\n", mFilename.c_str() );
319 void Indicator::LockFile::Unlock()
321 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
322 if( lockf( mFileDescriptor, F_ULOCK, 0 ) != 0 )
326 // file descriptor is no longer valid or not writable
329 DALI_LOG_ERROR( "### Cannot unlock indicator: bad file descriptor for %s\n", mFilename.c_str() );
334 bool Indicator::LockFile::RetrieveAndClearErrorStatus()
336 bool error = mErrorThrown;
337 mErrorThrown = false;
341 Indicator::ScopedLock::ScopedLock(LockFile* lockFile)
342 : mLockFile(lockFile),
347 mLocked = mLockFile->Lock();
351 Indicator::ScopedLock::~ScopedLock()
359 bool Indicator::ScopedLock::IsLocked()
364 Indicator::Indicator( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, Observer* observer )
367 mOpacityMode( Dali::Window::OPAQUE ),
368 mState( DISCONNECTED ),
370 mServerConnection( NULL ),
373 mObserver( observer ),
374 mOrientation( orientation ),
378 mVisible( Dali::Window::VISIBLE ),
380 mIsAnimationPlaying( false ),
381 mTouchedDown( false )
383 mIndicatorImageActor = Dali::ImageActor::New();
384 mIndicatorImageActor.SetBlendFunc( Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE_MINUS_SRC_ALPHA,
385 Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE );
387 mIndicatorImageActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
388 mIndicatorImageActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
391 mBackgroundActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
392 mBackgroundActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
393 mBackgroundActor.SetZ(-0.01f);
395 // add background to image actor to move it with indicator image
396 mIndicatorImageActor.Add( mBackgroundActor );
398 mIndicatorActor = Dali::Actor::New();
399 mIndicatorActor.Add( mIndicatorImageActor );
401 if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE )
403 mBackgroundActor.SetVisible( false );
407 mEventActor = Dali::Actor::New();
408 mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
409 mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
410 mEventActor.SetPosition(0.0f, 0.0f, 1.0f);
411 mEventActor.TouchedSignal().Connect( this, &Indicator::OnTouched );
412 mEventActor.SetLeaveRequired( true );
413 mIndicatorActor.Add( mEventActor );
417 // register indicator to accessibility manager
418 Dali::AccessibilityManager accessibilityManager = AccessibilityManager::Get();
419 if(accessibilityManager)
421 AccessibilityManager::GetImplementation( accessibilityManager ).SetIndicator( this );
425 Indicator::~Indicator()
429 mEventActor.TouchedSignal().Disconnect( this, &Indicator::OnTouched );
434 void Indicator::SetAdaptor(Adaptor* adaptor)
437 mIndicatorBuffer->SetAdaptor( adaptor );
440 Dali::Actor Indicator::GetActor()
442 return mIndicatorActor;
445 void Indicator::Open( Dali::Window::WindowOrientation orientation )
447 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
449 // Calls from Window should be set up to ensure we are in a
450 // disconnected state before opening a second time.
451 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
453 Connect( orientation );
455 // Change background visibility depending on orientation
456 if(mOrientation == Dali::Window::PORTRAIT || mOrientation == Dali::Window::PORTRAIT_INVERSE)
458 mBackgroundActor.SetVisible(true);
462 mBackgroundActor.SetVisible(false);
466 void Indicator::Close()
468 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s\n", STATE_DEBUG_STRING(mState) );
470 if( mState == CONNECTED )
473 if( mObserver != NULL )
475 mObserver->IndicatorClosed( this );
479 Dali::Image emptyImage;
480 mIndicatorImageActor.SetImage(emptyImage);
483 void Indicator::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
489 void Indicator::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode )
491 if ( visibleMode != mVisible )
493 // If we were previously hidden, then we should update the image data before we display the indicator
494 if ( mVisible == Dali::Window::INVISIBLE )
499 mVisible = visibleMode;
501 if( mIndicatorImageActor.GetImage() )
503 if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
506 ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
508 else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
511 ShowIndicator( KEEP_SHOWING );
516 ShowIndicator( HIDE_NOW );
522 bool Indicator::IsConnected()
524 return ( mState == CONNECTED );
527 bool Indicator::SendMessage( int messageDomain, int messageId, const void *data, int size )
531 return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
539 bool Indicator::OnTouched(Dali::Actor indicator, const Dali::TouchEvent& touchEvent)
541 if(mServerConnection)
543 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
545 // Send touch event to indicator server when indicator is showing
546 if( CheckVisibleState() || mIsShowing )
548 switch( touchPoint.state )
550 case Dali::TouchPoint::Down:
552 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
553 IpcDataEvMouseDown ipcDown( touchEvent.time );
554 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
555 mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
557 if( mVisible == Dali::Window::AUTO )
559 // Stop hiding indicator
560 ShowIndicator( KEEP_SHOWING );
561 mEventActor.SetSize( Dali::Stage::GetCurrent().GetSize() );
566 case Dali::TouchPoint::Motion:
568 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
569 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
573 case Dali::TouchPoint::Up:
575 IpcDataEvMouseUp ipcUp( touchEvent.time );
576 mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
578 if( mVisible == Dali::Window::AUTO )
581 ShowIndicator( 0.5f /* hide after 0.5 sec */ );
582 // TODO: not necessary if dali supports the event for both indicator and behind button
583 mEventActor.SetSize( mImageWidth, mImageHeight / 2 );
588 case Dali::TouchPoint::Leave:
590 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
591 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
592 IpcDataEvMouseUp ipcOut( touchEvent.time );
593 mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
601 // show indicator when it is invisible
602 else if( !mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
604 switch( touchPoint.state )
606 case Dali::TouchPoint::Down:
609 mTouchedYPosition = touchPoint.local.y;
613 case Dali::TouchPoint::Motion:
614 case Dali::TouchPoint::Up:
615 case Dali::TouchPoint::Leave:
619 if( touchPoint.local.y > mTouchedYPosition + mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE )
621 ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
622 mTouchedDown = false;
638 * Return the current orientation in degrees
639 * @return value of 0, 90, 180 or 270
641 int Indicator::OrientationToDegrees( Dali::Window::WindowOrientation orientation )
645 switch( orientation )
647 case Dali::Window::PORTRAIT:
650 case Dali::Window::PORTRAIT_INVERSE:
653 case Dali::Window::LANDSCAPE:
656 case Dali::Window::LANDSCAPE_INVERSE:
663 bool Indicator::Connect( Dali::Window::WindowOrientation orientation )
665 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
667 bool connected = false;
668 mOrientation = orientation;
669 mRotation = OrientationToDegrees(mOrientation);
671 switch( orientation )
673 case Dali::Window::PORTRAIT:
674 connected = Connect( ELM_INDICATOR_PORTRAIT );
676 case Dali::Window::PORTRAIT_INVERSE:
677 connected = Connect( ELM_INDICATOR_PORTRAIT );
679 case Dali::Window::LANDSCAPE:
680 connected = Connect( ELM_INDICATOR_LANDSCAPE );
682 case Dali::Window::LANDSCAPE_INVERSE:
683 connected = Connect( ELM_INDICATOR_LANDSCAPE );
690 bool Indicator::Connect( const char *serviceName )
692 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
694 bool connected = false;
696 mServerConnection = new ServerConnection( serviceName, 0, false, this );
697 if( mServerConnection )
699 connected = mServerConnection->IsConnected();
702 delete mServerConnection;
703 mServerConnection = NULL;
709 StartReconnectionTimer();
715 void Indicator::StartReconnectionTimer()
717 if( ! mReconnectTimer )
719 mReconnectTimer = Dali::Timer::New(1000);
720 mConnection.DisconnectAll();
721 mReconnectTimer.TickSignal().Connect( mConnection, &Indicator::OnReconnectTimer );
723 mReconnectTimer.Start();
726 bool Indicator::OnReconnectTimer()
730 if( mState == DISCONNECTED )
732 if( ! Connect( mOrientation ) )
741 void Indicator::Disconnect()
743 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
745 mState = DISCONNECTED;
753 delete mServerConnection;
754 mServerConnection = NULL;
757 void Indicator::NewLockFile( Ecore_Ipc_Event_Server_Data *epcEvent )
759 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
764 if ( (epcEvent->data) &&
765 (epcEvent->size > 0) &&
766 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
768 const char* lockFile = static_cast< const char* >( epcEvent->data );
769 mLock = new Indicator::LockFile( lockFile );
770 if( mLock->RetrieveAndClearErrorStatus() )
772 DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", lockFile );
777 void Indicator::Resize( int width, int height )
788 if( mImageWidth != width || mImageHeight != height )
791 mImageHeight = height;
793 // We don't currently handle the pixel buffer size being changed. Create a new image instead
801 void Indicator::LoadPixmapImage( Ecore_Ipc_Event_Server_Data *epcEvent )
803 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
805 // epcEvent->ref == w
806 // epcEvent->ref_to == h
807 // epcEvent->response == alpha
808 // epcEvent->data = pixmap id
809 if( ( epcEvent->data ) &&
810 (epcEvent->size >= (int)sizeof(PixmapId)) )
812 if( mSharedFile != NULL )
818 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
820 mImageWidth = epcEvent->ref;
821 mImageHeight = epcEvent->ref_to;
823 mPixmap = *(static_cast<PixmapId*>(epcEvent->data));
824 CreateNewPixmapImage();
826 if( CheckVisibleState() )
828 // set default indicator type (enable the quick panel)
829 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
833 // set default indicator type (disable the quick panel)
834 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
840 void Indicator::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
842 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
844 // epcEvent->ref == w
845 // epcEvent->ref_to == h
846 // epcEvent->response == alpha
847 // epcEvent->data = shm ref string + nul byte
848 if( ( epcEvent->data ) &&
849 ( ( unsigned char * ) epcEvent->data)[ epcEvent->size - 1 ] == 0 )
851 if( mSharedFile != NULL )
857 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
859 mImageWidth = epcEvent->ref;
860 mImageHeight = epcEvent->ref_to;
862 char* sharedFilename = static_cast<char*>(epcEvent->data);
864 mSharedFile = SharedFile::New( sharedFilename, mImageWidth * mImageWidth * 4, true );
865 if( mSharedFile != NULL )
868 mEventActor.SetSize(mImageWidth, mImageHeight);
870 if( CheckVisibleState() )
872 // set default indicator type (enable the quick panel)
873 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
877 // set default indicator type (disable the quick panel)
878 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
885 void Indicator::UpdateImageData()
887 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s mVisible: %s\n", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
889 if( mState == CONNECTED && mVisible )
897 mAdaptor->RequestUpdateOnce();
902 bool Indicator::CopyToBuffer()
904 bool success = false;
908 Indicator::ScopedLock scopedLock(mLock);
909 if( mLock->RetrieveAndClearErrorStatus() )
913 else if( scopedLock.IsLocked() )
915 unsigned char *src = mSharedFile->GetAddress();
916 size_t size = mImageWidth * mImageHeight * 4;
917 if( mIndicatorBuffer->UpdatePixels( src, size ) )
919 mAdaptor->RequestUpdateOnce();
928 void Indicator::SetBackground()
930 if( ! mBackgroundActor )
932 ConstructBackgroundMesh();
935 switch( mOpacityMode )
937 case Dali::Window::TRANSLUCENT:
939 SetMeshDataColors( mBackgroundMesh, GRADIENT_COLORS );
943 case Dali::Window::TRANSPARENT:
945 SetMeshDataColors( mBackgroundMesh, Color::TRANSPARENT );
949 case Dali::Window::OPAQUE:
952 SetMeshDataColors( mBackgroundMesh, Color::BLACK );
958 void Indicator::CreateNewPixmapImage()
960 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d\n", mImageWidth, mImageHeight );
961 Dali::PixmapImagePtr pixmapImage = Dali::PixmapImage::New(mPixmap, Dali::Adaptor::Get());
965 mIndicatorImageActor.SetImage( Dali::Image::New(*pixmapImage) );
966 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
967 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
968 mEventActor.SetSize(mImageWidth, mImageHeight);
971 if( mBackgroundActor )
973 mBackgroundActor.SetSize( mImageWidth, mImageHeight );
978 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
980 if( mObserver != NULL )
982 mObserver->IndicatorClosed( this );
984 // Don't do connection in this callback - strange things happen!
985 StartReconnectionTimer();
989 void Indicator::CreateNewImage()
991 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d\n", mImageWidth, mImageHeight );
992 mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mImageWidth, mImageHeight, Pixel::BGRA8888 );
993 Dali::Image image = Dali::Image::New( mIndicatorBuffer->GetNativeImage() );
995 if( CopyToBuffer() ) // Only create images if we have valid image buffer
997 mIndicatorImageActor.SetImage( image );
998 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
999 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
1000 mEventActor.SetSize(mImageWidth, mImageHeight);
1003 if( mBackgroundActor )
1005 mBackgroundActor.SetSize( mImageWidth, mImageHeight );
1010 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
1012 if( mObserver != NULL )
1014 mObserver->IndicatorClosed( this );
1016 // Don't do connection in this callback - strange things happen!
1017 StartReconnectionTimer();
1021 void Indicator::OnIndicatorTypeChanged( Type indicatorType )
1023 if( mObserver != NULL )
1025 mObserver->IndicatorTypeChanged( indicatorType );
1029 void Indicator::DataReceived( void* event )
1031 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1032 Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1034 switch( epcEvent->minor )
1037 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1040 case OP_UPDATE_DONE:
1041 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE\n" );
1046 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_LOCK_FILE\n" );
1047 NewLockFile( epcEvent );
1051 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF\n" );
1052 LoadSharedImage( epcEvent );
1056 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_PIXMAP_REF\n" );
1057 LoadPixmapImage( epcEvent );
1061 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1063 if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1065 IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1066 Resize( newSize->w, newSize->h );
1072 int msgDomain = epcEvent->ref;
1073 int msgId = epcEvent->ref_to;
1075 void *msgData = NULL;
1076 int msgDataSize = 0;
1077 msgData = epcEvent->data;
1078 msgDataSize = epcEvent->size;
1080 if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1084 case MSG_ID_INDICATOR_TYPE:
1086 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1087 Type* indicatorType = static_cast<Type*>( epcEvent->data );
1088 OnIndicatorTypeChanged( *indicatorType );
1092 case MSG_ID_INDICATOR_START_ANIMATION:
1094 if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1096 DALI_LOG_ERROR("Message data is incorrect");
1100 IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1102 if(!CheckVisibleState())
1104 ShowIndicator( animData->duration /* n sec */ );
1116 void Indicator::ConnectionClosed()
1118 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1120 // Will get this callback if the server connection failed to start up.
1121 delete mServerConnection;
1122 mServerConnection = NULL;
1123 mState = DISCONNECTED;
1125 // Attempt to re-connect
1126 Connect(mOrientation);
1129 bool Indicator::CheckVisibleState()
1131 if( mOrientation == Dali::Window::LANDSCAPE
1132 || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1133 || (mVisible != Dali::Window::VISIBLE) )
1141 void Indicator::ConstructBackgroundMesh()
1143 // Construct 5 interval mesh
1155 Dali::AnimatableMesh::Faces faces;
1156 faces.reserve(NUM_GRADIENT_INTERVALS * 6); // 2 tris per interval
1157 for(int i=0; i<NUM_GRADIENT_INTERVALS; i++)
1160 faces.push_back(j); faces.push_back(j+3); faces.push_back(j+1);
1161 faces.push_back(j); faces.push_back(j+2); faces.push_back(j+3);
1164 mBackgroundMesh = Dali::AnimatableMesh::New((NUM_GRADIENT_INTERVALS+1)*2, faces);
1165 float interval=1.0f / (float)NUM_GRADIENT_INTERVALS;
1166 for(int i=0;i<NUM_GRADIENT_INTERVALS+1;i++)
1169 mBackgroundMesh[j ].SetPosition(Vector3(-0.5f, -0.5f+(interval*(float)i), 0.0f));
1170 mBackgroundMesh[j+1].SetPosition(Vector3( 0.5f, -0.5f+(interval*(float)i), 0.0f));
1173 mBackgroundActor = Dali::MeshActor::New(mBackgroundMesh);
1174 mBackgroundActor.SetAffectedByLighting(false);
1175 Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( MESH_VERTEX_SHADER, MESH_FRAGMENT_SHADER,
1176 GEOMETRY_TYPE_MESH, // Using vertex color
1177 Dali::ShaderEffect::HINT_BLENDING );
1178 mBackgroundActor.SetShaderEffect(shaderEffect);
1181 void Indicator::ShowIndicator(float duration)
1183 if( !mIndicatorAnimation )
1185 mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1186 mIndicatorAnimation.FinishedSignal().Connect(this, &Indicator::OnAnimationFinished);
1189 if(mIsShowing && duration != 0)
1191 // do not need to show it again
1193 else if(!mIsShowing && mIsAnimationPlaying && duration == 0)
1195 // do not need to hide it again
1201 mIndicatorAnimation.MoveTo(mIndicatorImageActor, Vector3(0, -mImageHeight, 0), Dali::AlphaFunctions::EaseOut);
1205 OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1209 mIndicatorAnimation.MoveTo(mIndicatorImageActor, Vector3(0, 0, 0), Dali::AlphaFunctions::EaseOut);
1213 OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1216 mIndicatorAnimation.Play();
1217 mIsAnimationPlaying = true;
1224 mShowTimer = Dali::Timer::New(1000 * duration);
1225 mShowTimer.TickSignal().Connect(this, &Indicator::OnShowTimer);
1227 mShowTimer.SetInterval(1000* duration);
1230 if( mVisible == Dali::Window::AUTO )
1232 // check the stage touch
1233 Dali::Stage::GetCurrent().TouchedSignal().Connect( this, &Indicator::OnStageTouched );
1238 if(mShowTimer && mShowTimer.IsRunning())
1243 if( mVisible == Dali::Window::AUTO )
1245 // check the stage touch
1246 Dali::Stage::GetCurrent().TouchedSignal().Disconnect( this, &Indicator::OnStageTouched );
1251 bool Indicator::OnShowTimer()
1253 // after time up, hide indicator
1254 ShowIndicator( HIDE_NOW );
1259 void Indicator::OnAnimationFinished(Dali::Animation& animation)
1261 mIsAnimationPlaying = false;
1263 if( mIsShowing == false )
1265 // TODO: not necessary if dali supports the event for both indicator and behind button
1266 mEventActor.SetSize(mImageWidth, mImageHeight /2);
1270 mEventActor.SetSize(mImageWidth, mImageHeight);
1274 void Indicator::OnStageTouched(const Dali::TouchEvent& touchEvent)
1276 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
1278 // when stage is touched while indicator is showing temporary, hide it
1279 if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1281 switch( touchPoint.state )
1283 case Dali::TouchPoint::Down:
1285 ShowIndicator( HIDE_NOW );