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/bitmap-image.h>
32 #include <dali/public-api/adaptor-framework/common/pixmap-image.h>
33 #include <dali/public-api/actors/image-actor.h>
34 #include <dali/public-api/events/touch-event.h>
35 #include <dali/public-api/events/touch-point.h>
36 #include <dali/public-api/common/stage.h>
37 #include <dali/public-api/actors/blending.h>
38 #include <dali/public-api/shader-effects/shader-effect.h>
40 #include <dali/integration-api/debug.h>
43 #include <internal/common/adaptor-impl.h>
44 #include <internal/common/accessibility-manager-impl.h>
48 #if defined(DEBUG_ENABLED)
49 #define STATE_DEBUG_STRING(state) (state==DISCONNECTED?"DISCONNECTED":state==CONNECTED?"CONNECTED":"UNKNOWN")
55 const float SLIDING_ANIMATION_DURATION( 0.2f ); // 200 milli seconds
56 const float AUTO_INDICATOR_STAY_DURATION(3.0f); // 3 seconds
57 const float SHOWING_DISTANCE_HEIGHT_RATE(0.17f); // 10 pixels
65 const int NUM_GRADIENT_INTERVALS(5); // Number of gradient intervals
66 const Dali::Vector4 GRADIENT_COLORS[NUM_GRADIENT_INTERVALS+1] =
68 Vector4(0.0f, 0.0f, 0.0f, 0.6f),
69 Vector4(0.0f, 0.0f, 0.0f, 0.38f),
70 Vector4(0.0f, 0.0f, 0.0f, 0.20f),
71 Vector4(0.0f, 0.0f, 0.0f, 0.08f),
72 Vector4(0.0f, 0.0f, 0.0f, 0.0f),
73 Vector4(0.0f, 0.0f, 0.0f, 0.0f),
76 const float OPAQUE_THRESHOLD(0.99f);
77 const float TRANSPARENT_THRESHOLD(0.05f);
79 // Indicator orientation
80 const char* ELM_INDICATOR_PORTRAIT("elm_indicator_portrait");
81 const char* ELM_INDICATOR_LANDSCAPE("elm_indicator_landscape");
82 const char* ELM_INDICATOR_PORTRAIT_FIXED_COLOR_STYLE("elm_indicator_portrait_fixed");
83 const char* ELM_INDICATOR_LANDSCAPE_FIXED_COLOR_STYLE("elm_indicator_landscape_fixed");
85 const char* MESH_VERTEX_SHADER =
86 "attribute lowp vec3 aColor;\n"
87 "varying mediump vec4 vColor;\n"
90 " gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
91 " vColor = vec4(aColor.r, aColor.g, aColor.b, aTexCoord.x);\n"
94 const char* MESH_FRAGMENT_SHADER =
95 "varying mediump vec4 vColor;\n"
98 " gl_FragColor = vColor*uColor;\n"
101 // Copied from elm_win.h
104 * Defines the type modes of indicator that can be shown
105 * If the indicator can support several type of indicator,
106 * you can use this enum value to deal with different type of indicator
110 ELM_WIN_INDICATOR_TYPE_UNKNOWN, /**< Unknown indicator type mode */
111 ELM_WIN_INDICATOR_TYPE_1, /**< Type 0 the the indicator */
112 ELM_WIN_INDICATOR_TYPE_2, /**< Type 1 the indicator */
113 } Elm_Win_Indicator_Type_Mode;
115 // Copied from ecore_evas_extn.c
145 // Copied from elm_conform.c
147 const int MSG_DOMAIN_CONTROL_INDICATOR(0x10001);
148 const int MSG_ID_INDICATOR_REPEAT_EVENT(0x10002);
149 const int MSG_ID_INDICATOR_ROTATION(0x10003);
150 const int MSG_ID_INDICATOR_OPACITY(0X1004);
151 const int MSG_ID_INDICATOR_TYPE(0X1005);
152 const int MSG_ID_INDICATOR_START_ANIMATION(0X10006);
164 struct IpcIndicatorDataAnimation
170 struct IpcDataEvMouseUp
173 Evas_Button_Flags flags;
175 unsigned int timestamp;
176 Evas_Event_Flags event_flags;
178 IpcDataEvMouseUp(unsigned long timestamp)
180 flags(EVAS_BUTTON_NONE),
182 timestamp(static_cast<unsigned int>(timestamp)),
183 event_flags(EVAS_EVENT_FLAG_NONE)
188 struct IpcDataEvMouseDown
191 Evas_Button_Flags flags;
193 unsigned int timestamp;
194 Evas_Event_Flags event_flags;
196 IpcDataEvMouseDown(unsigned long timestamp)
198 flags(EVAS_BUTTON_NONE),
200 timestamp(static_cast<unsigned int>(timestamp)),
201 event_flags(EVAS_EVENT_FLAG_NONE)
206 struct IpcDataEvMouseMove
209 Evas_Button_Flags flags;
211 unsigned int timestamp;
212 Evas_Event_Flags event_flags;
214 IpcDataEvMouseMove(const Dali::TouchPoint& touchPoint, unsigned long timestamp)
215 : x(static_cast<Evas_Coord>(touchPoint.local.x)),
216 y(static_cast<Evas_Coord>(touchPoint.local.y)),
217 flags(EVAS_BUTTON_NONE),
219 timestamp(static_cast<unsigned int>(timestamp)),
220 event_flags(EVAS_EVENT_FLAG_NONE)
225 struct IpcDataEvMouseOut
227 unsigned int timestamp;
229 Evas_Event_Flags event_flags;
231 IpcDataEvMouseOut(unsigned long timestamp)
232 : timestamp(static_cast<unsigned int>(timestamp)),
234 event_flags(EVAS_EVENT_FLAG_NONE)
239 void SetMeshDataColors(Dali::AnimatableMesh mesh, const Vector4 (&colors)[NUM_GRADIENT_INTERVALS+1])
241 for( size_t i=0; i<NUM_GRADIENT_INTERVALS+1; i++ )
244 mesh[j].SetColor(colors[i]);
245 mesh[j+1].SetColor(colors[i]);
246 mesh[j].SetTextureCoords(Dali::Vector2(colors[i].a, colors[i].a));
247 mesh[j+1].SetTextureCoords(Dali::Vector2(colors[i].a, colors[i].a));
251 void SetMeshDataColors(Dali::AnimatableMesh mesh, const Vector4& color)
253 for( size_t i=0, length=NUM_GRADIENT_INTERVALS+1 ; i<length; i++ )
256 mesh[j].SetColor(color);
257 mesh[j+1].SetColor(color);
258 mesh[j].SetTextureCoords(Dali::Vector2(color.a, color.a));
259 mesh[j+1].SetTextureCoords(Dali::Vector2(color.a, color.a));
263 } // anonymous namespace
272 #if defined(DEBUG_ENABLED)
273 Debug::Filter* gIndicatorLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_INDICATOR");
277 Indicator::LockFile::LockFile(const char* filename)
278 : mFilename(filename),
281 mFileDescriptor = open(filename, O_RDWR);
282 if( mFileDescriptor == -1 )
286 DALI_LOG_ERROR( "### Cannot open %s for indicator lock ###\n", mFilename.c_str() );
290 Indicator::LockFile::~LockFile()
292 // Closing file descriptor also unlocks file.
293 close( mFileDescriptor );
296 bool Indicator::LockFile::Lock()
298 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
301 if( mFileDescriptor > 0 )
303 if( lockf( mFileDescriptor, F_LOCK, 0 ) == 0 ) // Note, operation may block.
311 // file descriptor is no longer valid or not writable
314 DALI_LOG_ERROR( "### Cannot lock indicator: bad file descriptor for %s ###\n", mFilename.c_str() );
322 void Indicator::LockFile::Unlock()
324 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
325 if( lockf( mFileDescriptor, F_ULOCK, 0 ) != 0 )
329 // file descriptor is no longer valid or not writable
332 DALI_LOG_ERROR( "### Cannot unlock indicator: bad file descriptor for %s\n", mFilename.c_str() );
337 bool Indicator::LockFile::RetrieveAndClearErrorStatus()
339 bool error = mErrorThrown;
340 mErrorThrown = false;
344 Indicator::ScopedLock::ScopedLock(LockFile* lockFile)
345 : mLockFile(lockFile),
350 mLocked = mLockFile->Lock();
354 Indicator::ScopedLock::~ScopedLock()
362 bool Indicator::ScopedLock::IsLocked()
367 Indicator::Indicator( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, Dali::Window::IndicatorStyle style, Observer* observer )
371 mOpacityMode( Dali::Window::OPAQUE ),
372 mState( DISCONNECTED ),
374 mServerConnection( NULL ),
377 mObserver( observer ),
378 mOrientation( orientation ),
382 mVisible( Dali::Window::VISIBLE ),
384 mIsAnimationPlaying( false ),
385 mTouchedDown( false )
387 mIndicatorImageActor = Dali::ImageActor::New();
388 mIndicatorImageActor.SetBlendFunc( Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE_MINUS_SRC_ALPHA,
389 Dali::BlendingFactor::ONE, Dali::BlendingFactor::ONE );
391 mIndicatorImageActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
392 mIndicatorImageActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
395 mBackgroundActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
396 mBackgroundActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
397 mBackgroundActor.SetZ(-0.01f);
399 // add background to image actor to move it with indicator image
400 mIndicatorImageActor.Add( mBackgroundActor );
402 mIndicatorActor = Dali::Actor::New();
403 mIndicatorActor.Add( mIndicatorImageActor );
405 if( mOrientation == Dali::Window::LANDSCAPE || mOrientation == Dali::Window::LANDSCAPE_INVERSE )
407 mBackgroundActor.SetVisible( false );
411 mEventActor = Dali::Actor::New();
412 mEventActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
413 mEventActor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
414 mEventActor.SetPosition(0.0f, 0.0f, 1.0f);
415 mEventActor.TouchedSignal().Connect( this, &Indicator::OnTouched );
416 mEventActor.SetLeaveRequired( true );
417 mIndicatorActor.Add( mEventActor );
421 // register indicator to accessibility manager
422 Dali::AccessibilityManager accessibilityManager = AccessibilityManager::Get();
423 if(accessibilityManager)
425 AccessibilityManager::GetImplementation( accessibilityManager ).SetIndicator( this );
429 Indicator::~Indicator()
433 mEventActor.TouchedSignal().Disconnect( this, &Indicator::OnTouched );
438 void Indicator::SetAdaptor(Adaptor* adaptor)
441 mIndicatorBuffer->SetAdaptor( adaptor );
444 Dali::Actor Indicator::GetActor()
446 return mIndicatorActor;
449 void Indicator::Open( Dali::Window::WindowOrientation orientation )
451 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
453 // Calls from Window should be set up to ensure we are in a
454 // disconnected state before opening a second time.
455 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
457 Connect( orientation );
459 // Change background visibility depending on orientation
460 if(mOrientation == Dali::Window::PORTRAIT || mOrientation == Dali::Window::PORTRAIT_INVERSE)
462 mBackgroundActor.SetVisible(true);
466 mBackgroundActor.SetVisible(false);
470 void Indicator::Close()
472 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s\n", STATE_DEBUG_STRING(mState) );
474 if( mState == CONNECTED )
477 if( mObserver != NULL )
479 mObserver->IndicatorClosed( this );
483 Dali::Image emptyImage;
484 mIndicatorImageActor.SetImage(emptyImage);
487 void Indicator::SetOpacityMode( Dali::Window::IndicatorBgOpacity mode )
493 void Indicator::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
495 if ( visibleMode != mVisible || forceUpdate )
497 // If we were previously hidden, then we should update the image data before we display the indicator
498 if ( mVisible == Dali::Window::INVISIBLE )
503 mVisible = visibleMode;
505 if( mIndicatorImageActor.GetImage() )
507 if( CheckVisibleState() && mVisible == Dali::Window::AUTO )
510 ShowIndicator( AUTO_INDICATOR_STAY_DURATION /* stay n sec */ );
512 else if( CheckVisibleState() && mVisible == Dali::Window::VISIBLE )
515 ShowIndicator( KEEP_SHOWING );
520 ShowIndicator( HIDE_NOW );
526 bool Indicator::IsConnected()
528 return ( mState == CONNECTED );
531 bool Indicator::SendMessage( int messageDomain, int messageId, const void *data, int size )
535 return mServerConnection->SendEvent( OP_MSG, messageDomain, messageId, data, size );
543 bool Indicator::OnTouched(Dali::Actor indicator, const Dali::TouchEvent& touchEvent)
545 if(mServerConnection)
547 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
549 // Send touch event to indicator server when indicator is showing
550 if( CheckVisibleState() || mIsShowing )
552 switch( touchPoint.state )
554 case Dali::TouchPoint::Down:
556 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
557 IpcDataEvMouseDown ipcDown( touchEvent.time );
558 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
559 mServerConnection->SendEvent( OP_EV_MOUSE_DOWN, &ipcDown, sizeof(ipcDown) );
561 if( mVisible == Dali::Window::AUTO )
563 // Stop hiding indicator
564 ShowIndicator( KEEP_SHOWING );
565 mEventActor.SetSize( Dali::Stage::GetCurrent().GetSize() );
570 case Dali::TouchPoint::Motion:
572 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
573 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
577 case Dali::TouchPoint::Up:
579 IpcDataEvMouseUp ipcUp( touchEvent.time );
580 mServerConnection->SendEvent( OP_EV_MOUSE_UP, &ipcUp, sizeof(ipcUp) );
582 if( mVisible == Dali::Window::AUTO )
585 ShowIndicator( 0.5f /* hide after 0.5 sec */ );
586 // TODO: not necessary if dali supports the event for both indicator and behind button
587 mEventActor.SetSize( mImageWidth, mImageHeight / 2 );
592 case Dali::TouchPoint::Leave:
594 IpcDataEvMouseMove ipcMove( touchPoint, touchEvent.time );
595 mServerConnection->SendEvent( OP_EV_MOUSE_MOVE, &ipcMove, sizeof(ipcMove) );
596 IpcDataEvMouseUp ipcOut( touchEvent.time );
597 mServerConnection->SendEvent( OP_EV_MOUSE_OUT, &ipcOut, sizeof(ipcOut) );
605 // show indicator when it is invisible
606 else if( !mIsShowing && ( CheckVisibleState() == false && mVisible == Dali::Window::AUTO ) )
608 switch( touchPoint.state )
610 case Dali::TouchPoint::Down:
613 mTouchDownPosition = touchPoint.local;
618 case Dali::TouchPoint::Motion:
619 case Dali::TouchPoint::Up:
620 case Dali::TouchPoint::Leave:
624 float moveDistance = sqrt( (mTouchDownPosition.x - touchPoint.local.x) * (mTouchDownPosition.x - touchPoint.local.x)
625 + (mTouchDownPosition.y - touchPoint.local.y)*(mTouchDownPosition.y - touchPoint.local.y) );
627 if( moveDistance > 2 * (mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE) /*threshold for distance*/
628 && touchPoint.local.y - mTouchDownPosition.y > mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE /*threshold for y*/ )
630 ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
631 mTouchedDown = false;
647 * Return the current orientation in degrees
648 * @return value of 0, 90, 180 or 270
650 int Indicator::OrientationToDegrees( Dali::Window::WindowOrientation orientation )
654 switch( orientation )
656 case Dali::Window::PORTRAIT:
659 case Dali::Window::PORTRAIT_INVERSE:
662 case Dali::Window::LANDSCAPE:
665 case Dali::Window::LANDSCAPE_INVERSE:
672 bool Indicator::Connect( Dali::Window::WindowOrientation orientation )
674 DALI_ASSERT_DEBUG( mState == DISCONNECTED );
676 bool connected = false;
677 mOrientation = orientation;
678 mRotation = OrientationToDegrees(mOrientation);
680 switch( orientation )
682 case Dali::Window::PORTRAIT:
683 if(mStyle == Dali::Window::FIXED_COLOR)
685 connected = Connect( ELM_INDICATOR_PORTRAIT_FIXED_COLOR_STYLE );
689 connected = Connect( ELM_INDICATOR_PORTRAIT );
692 case Dali::Window::PORTRAIT_INVERSE:
693 if(mStyle == Dali::Window::FIXED_COLOR)
695 connected = Connect( ELM_INDICATOR_PORTRAIT_FIXED_COLOR_STYLE );
699 connected = Connect( ELM_INDICATOR_PORTRAIT );
702 case Dali::Window::LANDSCAPE:
703 if(mStyle == Dali::Window::FIXED_COLOR)
705 connected = Connect( ELM_INDICATOR_LANDSCAPE_FIXED_COLOR_STYLE );
709 connected = Connect( ELM_INDICATOR_LANDSCAPE );
712 case Dali::Window::LANDSCAPE_INVERSE:
713 if(mStyle == Dali::Window::FIXED_COLOR)
715 connected = Connect( ELM_INDICATOR_LANDSCAPE_FIXED_COLOR_STYLE );
719 connected = Connect( ELM_INDICATOR_LANDSCAPE );
727 bool Indicator::Connect( const char *serviceName )
729 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
731 bool connected = false;
733 mServerConnection = new ServerConnection( serviceName, 0, false, this );
734 if( mServerConnection )
736 connected = mServerConnection->IsConnected();
739 delete mServerConnection;
740 mServerConnection = NULL;
746 StartReconnectionTimer();
756 void Indicator::StartReconnectionTimer()
758 if( ! mReconnectTimer )
760 mReconnectTimer = Dali::Timer::New(1000);
761 mConnection.DisconnectAll();
762 mReconnectTimer.TickSignal().Connect( mConnection, &Indicator::OnReconnectTimer );
764 mReconnectTimer.Start();
767 bool Indicator::OnReconnectTimer()
771 if( mState == DISCONNECTED )
773 if( ! Connect( mOrientation ) )
782 void Indicator::Disconnect()
784 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
786 mState = DISCONNECTED;
794 delete mServerConnection;
795 mServerConnection = NULL;
798 void Indicator::NewLockFile( Ecore_Ipc_Event_Server_Data *epcEvent )
800 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
805 if ( (epcEvent->data) &&
806 (epcEvent->size > 0) &&
807 (((unsigned char *)epcEvent->data)[epcEvent->size - 1] == 0) )
809 const char* lockFile = static_cast< const char* >( epcEvent->data );
810 mLock = new Indicator::LockFile( lockFile );
811 if( mLock->RetrieveAndClearErrorStatus() )
813 DALI_LOG_ERROR( "### Indicator error: Cannot open lock file %s ###\n", lockFile );
818 void Indicator::Resize( int width, int height )
829 if( mImageWidth != width || mImageHeight != height )
832 mImageHeight = height;
834 // We don't currently handle the pixel buffer size being changed. Create a new image instead
842 void Indicator::LoadPixmapImage( Ecore_Ipc_Event_Server_Data *epcEvent )
844 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
846 // epcEvent->ref == w
847 // epcEvent->ref_to == h
848 // epcEvent->response == alpha
849 // epcEvent->data = pixmap id
850 if( ( epcEvent->data ) &&
851 (epcEvent->size >= (int)sizeof(PixmapId)) )
853 if( mSharedFile != NULL )
859 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
861 mImageWidth = epcEvent->ref;
862 mImageHeight = epcEvent->ref_to;
864 mPixmap = *(static_cast<PixmapId*>(epcEvent->data));
865 CreateNewPixmapImage();
867 if( CheckVisibleState() )
869 // set default indicator type (enable the quick panel)
870 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
874 // set default indicator type (disable the quick panel)
875 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
878 SetVisible(mVisible, true);
883 void Indicator::LoadSharedImage( Ecore_Ipc_Event_Server_Data *epcEvent )
885 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
887 // epcEvent->ref == w
888 // epcEvent->ref_to == h
889 // epcEvent->response == alpha
890 // epcEvent->data = shm ref string + nul byte
891 if( ( epcEvent->data ) &&
892 ( ( unsigned char * ) epcEvent->data)[ epcEvent->size - 1 ] == 0 )
894 if( mSharedFile != NULL )
900 if( (epcEvent->ref > 0) && (epcEvent->ref_to > 0) )
902 mImageWidth = epcEvent->ref;
903 mImageHeight = epcEvent->ref_to;
905 char* sharedFilename = static_cast<char*>(epcEvent->data);
907 mSharedFile = SharedFile::New( sharedFilename, mImageWidth * mImageWidth * 4, true );
908 if( mSharedFile != NULL )
911 mEventActor.SetSize(mImageWidth, mImageHeight);
913 if( CheckVisibleState() )
915 // set default indicator type (enable the quick panel)
916 OnIndicatorTypeChanged( INDICATOR_TYPE_1 );
920 // set default indicator type (disable the quick panel)
921 OnIndicatorTypeChanged( INDICATOR_TYPE_2 );
924 SetVisible(mVisible, true);
930 void Indicator::UpdateImageData()
932 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "State: %s mVisible: %s\n", STATE_DEBUG_STRING(mState), mVisible?"T":"F" );
934 if( mState == CONNECTED && mVisible )
942 mAdaptor->RequestUpdateOnce();
947 bool Indicator::CopyToBuffer()
949 bool success = false;
953 Indicator::ScopedLock scopedLock(mLock);
954 if( mLock->RetrieveAndClearErrorStatus() )
958 else if( scopedLock.IsLocked() )
960 unsigned char *src = mSharedFile->GetAddress();
961 size_t size = mImageWidth * mImageHeight * 4;
963 if( mIndicatorBuffer->UpdatePixels( src, size ) )
965 mAdaptor->RequestUpdateOnce();
974 void Indicator::SetBackground()
976 if( ! mBackgroundActor )
978 ConstructBackgroundMesh();
981 switch( mOpacityMode )
983 case Dali::Window::TRANSLUCENT:
985 SetMeshDataColors( mBackgroundMesh, GRADIENT_COLORS );
989 case Dali::Window::TRANSPARENT:
991 SetMeshDataColors( mBackgroundMesh, Color::TRANSPARENT );
995 case Dali::Window::OPAQUE:
998 SetMeshDataColors( mBackgroundMesh, Color::BLACK );
1004 void Indicator::CreateNewPixmapImage()
1006 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d\n", mImageWidth, mImageHeight );
1007 Dali::PixmapImagePtr pixmapImage = Dali::PixmapImage::New(mPixmap, Dali::Adaptor::Get());
1011 mIndicatorImageActor.SetImage( Dali::Image::New(*pixmapImage) );
1012 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
1013 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
1014 mEventActor.SetSize(mImageWidth, mImageHeight);
1017 if( mBackgroundActor )
1019 mBackgroundActor.SetSize( mImageWidth, mImageHeight );
1024 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
1026 if( mObserver != NULL )
1028 mObserver->IndicatorClosed( this );
1030 // Don't do connection in this callback - strange things happen!
1031 StartReconnectionTimer();
1035 void Indicator::CreateNewImage()
1037 DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d\n", mImageWidth, mImageHeight );
1038 mIndicatorBuffer = new IndicatorBuffer( mAdaptor, mImageWidth, mImageHeight, Pixel::BGRA8888 );
1039 Dali::Image image = Dali::Image::New( mIndicatorBuffer->GetNativeImage() );
1041 if( CopyToBuffer() ) // Only create images if we have valid image buffer
1043 mIndicatorImageActor.SetImage( image );
1044 mIndicatorImageActor.SetSize( mImageWidth, mImageHeight );
1045 mIndicatorActor.SetSize( mImageWidth, mImageHeight );
1046 mEventActor.SetSize(mImageWidth, mImageHeight);
1049 if( mBackgroundActor )
1051 mBackgroundActor.SetSize( mImageWidth, mImageHeight );
1056 DALI_LOG_WARNING("### Cannot create indicator image - disconnecting ###\n");
1058 if( mObserver != NULL )
1060 mObserver->IndicatorClosed( this );
1062 // Don't do connection in this callback - strange things happen!
1063 StartReconnectionTimer();
1067 void Indicator::OnIndicatorTypeChanged( Type indicatorType )
1069 if( mObserver != NULL )
1071 mObserver->IndicatorTypeChanged( indicatorType );
1075 void Indicator::DataReceived( void* event )
1077 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1078 Ecore_Ipc_Event_Server_Data *epcEvent = static_cast<Ecore_Ipc_Event_Server_Data *>( event );
1080 switch( epcEvent->minor )
1083 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
1086 mAdaptor->RequestUpdateOnce();
1090 case OP_UPDATE_DONE:
1091 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE\n" );
1096 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_LOCK_FILE\n" );
1097 NewLockFile( epcEvent );
1101 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_SHM_REF\n" );
1102 LoadSharedImage( epcEvent );
1106 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_PIXMAP_REF\n" );
1107 LoadPixmapImage( epcEvent );
1111 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_RESIZE\n" );
1113 if( (epcEvent->data) && (epcEvent->size >= (int)sizeof(IpcDataResize)) )
1115 IpcDataResize *newSize = static_cast<IpcDataResize*>( epcEvent->data );
1116 Resize( newSize->w, newSize->h );
1122 int msgDomain = epcEvent->ref;
1123 int msgId = epcEvent->ref_to;
1125 void *msgData = NULL;
1126 int msgDataSize = 0;
1127 msgData = epcEvent->data;
1128 msgDataSize = epcEvent->size;
1130 if( msgDomain == MSG_DOMAIN_CONTROL_INDICATOR )
1134 case MSG_ID_INDICATOR_TYPE:
1136 DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_MSG_PARENT, INDICATOR_TYPE\n" );
1137 Type* indicatorType = static_cast<Type*>( epcEvent->data );
1138 OnIndicatorTypeChanged( *indicatorType );
1142 case MSG_ID_INDICATOR_START_ANIMATION:
1144 if (msgDataSize != (int)sizeof(IpcIndicatorDataAnimation))
1146 DALI_LOG_ERROR("Message data is incorrect");
1150 IpcIndicatorDataAnimation *animData = static_cast<IpcIndicatorDataAnimation*>(msgData);
1152 if(!CheckVisibleState())
1154 ShowIndicator( animData->duration /* n sec */ );
1166 void Indicator::ConnectionClosed()
1168 DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
1170 // Will get this callback if the server connection failed to start up.
1171 delete mServerConnection;
1172 mServerConnection = NULL;
1173 mState = DISCONNECTED;
1175 // Attempt to re-connect
1176 Connect(mOrientation);
1179 bool Indicator::CheckVisibleState()
1181 if( mOrientation == Dali::Window::LANDSCAPE
1182 || mOrientation == Dali::Window::LANDSCAPE_INVERSE
1183 || (mVisible != Dali::Window::VISIBLE) )
1191 void Indicator::ConstructBackgroundMesh()
1193 // Construct 5 interval mesh
1205 Dali::AnimatableMesh::Faces faces;
1206 faces.reserve(NUM_GRADIENT_INTERVALS * 6); // 2 tris per interval
1207 for(int i=0; i<NUM_GRADIENT_INTERVALS; i++)
1210 faces.push_back(j); faces.push_back(j+3); faces.push_back(j+1);
1211 faces.push_back(j); faces.push_back(j+2); faces.push_back(j+3);
1214 mBackgroundMesh = Dali::AnimatableMesh::New((NUM_GRADIENT_INTERVALS+1)*2, faces);
1215 float interval=1.0f / (float)NUM_GRADIENT_INTERVALS;
1216 for(int i=0;i<NUM_GRADIENT_INTERVALS+1;i++)
1219 mBackgroundMesh[j ].SetPosition(Vector3(-0.5f, -0.5f+(interval*(float)i), 0.0f));
1220 mBackgroundMesh[j+1].SetPosition(Vector3( 0.5f, -0.5f+(interval*(float)i), 0.0f));
1223 mBackgroundActor = Dali::MeshActor::New(mBackgroundMesh);
1224 mBackgroundActor.SetAffectedByLighting(false);
1225 Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( MESH_VERTEX_SHADER, MESH_FRAGMENT_SHADER,
1226 GEOMETRY_TYPE_MESH, // Using vertex color
1227 Dali::ShaderEffect::HINT_BLENDING );
1228 mBackgroundActor.SetShaderEffect(shaderEffect);
1231 void Indicator::ShowIndicator(float duration)
1233 if( !mIndicatorAnimation )
1235 mIndicatorAnimation = Dali::Animation::New(SLIDING_ANIMATION_DURATION);
1236 mIndicatorAnimation.FinishedSignal().Connect(this, &Indicator::OnAnimationFinished);
1239 if(mIsShowing && duration != 0)
1241 // do not need to show it again
1243 else if(!mIsShowing && mIsAnimationPlaying && duration == 0)
1245 // do not need to hide it again
1251 mIndicatorAnimation.MoveTo(mIndicatorImageActor, Vector3(0, -mImageHeight, 0), Dali::AlphaFunctions::EaseOut);
1255 OnIndicatorTypeChanged( INDICATOR_TYPE_2 ); // un-toucable
1259 mIndicatorAnimation.MoveTo(mIndicatorImageActor, Vector3(0, 0, 0), Dali::AlphaFunctions::EaseOut);
1263 OnIndicatorTypeChanged( INDICATOR_TYPE_1 ); // touchable
1266 mIndicatorAnimation.Play();
1267 mIsAnimationPlaying = true;
1274 mShowTimer = Dali::Timer::New(1000 * duration);
1275 mShowTimer.TickSignal().Connect(this, &Indicator::OnShowTimer);
1277 mShowTimer.SetInterval(1000* duration);
1280 if( mVisible == Dali::Window::AUTO )
1282 // check the stage touch
1283 Dali::Stage::GetCurrent().TouchedSignal().Connect( this, &Indicator::OnStageTouched );
1288 if(mShowTimer && mShowTimer.IsRunning())
1293 if( mVisible == Dali::Window::AUTO )
1295 // check the stage touch
1296 Dali::Stage::GetCurrent().TouchedSignal().Disconnect( this, &Indicator::OnStageTouched );
1301 bool Indicator::OnShowTimer()
1303 // after time up, hide indicator
1304 ShowIndicator( HIDE_NOW );
1309 void Indicator::OnAnimationFinished(Dali::Animation& animation)
1311 mIsAnimationPlaying = false;
1313 if( mIsShowing == false )
1315 // TODO: not necessary if dali supports the event for both indicator and behind button
1316 mEventActor.SetSize(mImageWidth, mImageHeight /2);
1320 mEventActor.SetSize(mImageWidth, mImageHeight);
1324 void Indicator::OnStageTouched(const Dali::TouchEvent& touchEvent)
1326 const TouchPoint& touchPoint = touchEvent.GetPoint( 0 );
1328 // when stage is touched while indicator is showing temporary, hide it
1329 if( mIsShowing && ( CheckVisibleState() == false || mVisible == Dali::Window::AUTO ) )
1331 switch( touchPoint.state )
1333 case Dali::TouchPoint::Down:
1335 ShowIndicator( HIDE_NOW );