Replace pepper dali with remote surface
[platform/core/uifw/widget-viewer-dali.git] / internal / widget_view / widget_view_impl.cpp
1 /*
2  * Samsung API
3  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Flora License, Version 1.1 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://floralicense.org/license/
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 // CLASS HEADER
19 #include <internal/widget_view/widget_view_impl.h>
20
21 // INTERNAL INCLUDES
22
23 // EXTERNAL INCLUDES
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/events/touch-data.h>
26 #include <dali/public-api/events/wheel-event.h>
27 #include <dali/public-api/images/native-image.h>
28 #include <dali/integration-api/debug.h>
29 #include <string.h>
30 #include <Ecore_Input.h>
31 #include <widget_service.h>
32 #include <widget_instance.h>
33 #include <tzplatform_config.h>
34 #include <wayland-extension/tizen-extension-client-protocol.h>
35 #include <aul_rsm_viewer.h>
36
37 namespace Dali
38 {
39
40 namespace WidgetView
41 {
42
43 namespace Internal
44 {
45
46 namespace
47 {
48
49 #define WIDGET_VIEW_RESOURCE_DEFAULT_IMG "/widget_viewer_dali/images/unknown.png"
50
51 #if defined(DEBUG_ENABLED)
52 Integration::Log::Filter* gWidgetViewLogging  = Integration::Log::Filter::New( Debug::Verbose, false, "LOG_WIDGET_VIEW" );
53 #endif
54
55 static Eina_Bool OnKeyDown( void* data, int type, void* eventInfo )
56 {
57   Ecore_Event_Key *event = static_cast< Ecore_Event_Key* >( eventInfo );
58   tizen_remote_surface* surface = static_cast< tizen_remote_surface* >( data );
59
60   tizen_remote_surface_transfer_key_event( surface,
61                                            TIZEN_REMOTE_SURFACE_EVENT_TYPE_KEY_DOWN,
62                                            event->keycode,
63                                            ecore_device_class_get(event->dev),
64                                            ecore_device_subclass_get(event->dev),
65                                            ecore_device_identifier_get(event->dev),
66                                            event->timestamp
67                                          );
68
69   return EINA_TRUE;
70 }
71
72 static Eina_Bool OnKeyUp(void* data, int type, void* eventInfo)
73 {
74   Ecore_Event_Key *event = static_cast< Ecore_Event_Key* >( eventInfo );
75   tizen_remote_surface* surface = static_cast< tizen_remote_surface* >( data );
76
77   tizen_remote_surface_transfer_key_event( surface,
78                                            TIZEN_REMOTE_SURFACE_EVENT_TYPE_KEY_UP,
79                                            event->keycode,
80                                            ecore_device_class_get(event->dev),
81                                            ecore_device_subclass_get(event->dev),
82                                            ecore_device_identifier_get(event->dev),
83                                            event->timestamp
84                                          );
85   return EINA_TRUE;
86 }
87
88 static void OnSurfaceUpdate( struct tizen_remote_surface* surface, wl_buffer* buffer, uint32_t time, void* data )
89 {
90   Dali::WidgetView::Internal::WidgetView* widgetView = static_cast< Dali::WidgetView::Internal::WidgetView* >( data );
91
92   if( widgetView && !widgetView->IsWidgetImageView() )
93   {
94     tizen_remote_surface_transfer_visibility( surface, TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE);
95
96     widgetView->CreateWidgetImageView();
97     widgetView->ConnectSignal( surface );
98     ecore_event_handler_add( ECORE_EVENT_KEY_DOWN, OnKeyDown, surface );
99     ecore_event_handler_add( ECORE_EVENT_KEY_UP, OnKeyUp, surface );
100
101   }
102
103   //get tbm surface from buffer
104   tbm_surface_h tbmSurface = static_cast< tbm_surface_h >( wl_buffer_get_user_data( buffer ) );
105   widgetView->UpdateImageSource( tbmSurface );
106 }
107
108 static void OnSurfaceMissing( struct tizen_remote_surface* surface, void* data )
109 {
110   //ToDo: WidgetDeletedSignal
111 }
112
113
114 static struct aul_rsm_handler_s remoteSurfaceHandler = {
115   OnSurfaceUpdate,
116   OnSurfaceMissing,
117 };
118
119 } // unnamed namespace
120
121 Dali::WidgetView::WidgetView WidgetView::New( const std::string& widgetId, const std::string& contentInfo, int width, int height, double updatePeriod )
122 {
123   // Create the implementation, temporarily owned on stack
124   IntrusivePtr< WidgetView > internalWidgetView = new WidgetView( widgetId, contentInfo, width, height, updatePeriod );
125
126   // Pass ownership to CustomActor
127   Dali::WidgetView::WidgetView widgetView( *internalWidgetView );
128
129   // Second-phase init of the implementation
130   // This can only be done after the CustomActor connection has been made...
131   internalWidgetView->Initialize();
132
133   return widgetView;
134 }
135
136 WidgetView::WidgetView()
137 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
138   mWidgetId(),
139   mInstanceId(),
140   mContentInfo(),
141   mTitle(),
142   mBundle( NULL ),
143   mWidth( 0 ),
144   mHeight( 0 ),
145   mPid( 0 ),
146   mUpdatePeriod( 0.0 ),
147   mPreviewEnabled( true ),
148   mStateTextEnabled( true ),
149   mPermanentDelete( true )
150 {
151 }
152
153 WidgetView::WidgetView( const std::string& widgetId, const std::string& contentInfo, int width, int height, double updatePeriod )
154 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
155   mWidgetId( widgetId ),
156   mInstanceId(),
157   mContentInfo( contentInfo ),
158   mTitle(),
159   mBundle( NULL ),
160   mWidth( width ),
161   mHeight( height ),
162   mPid( 0 ),
163   mUpdatePeriod( updatePeriod ),
164   mPreviewEnabled( true ),
165   mStateTextEnabled( true ),
166   mPermanentDelete( true )
167 {
168 }
169
170 WidgetView::~WidgetView()
171 {
172   if( !mWidgetId.empty() && !mInstanceId.empty() )
173   {
174     widget_instance_terminate( mInstanceId.c_str() );
175
176     if( mPermanentDelete )
177     {
178       widget_instance_destroy( mInstanceId.c_str() );
179     }
180   }
181
182   if( mBundle )
183   {
184     bundle_free( mBundle );
185   }
186 }
187
188 bool WidgetView::PauseWidget()
189 {
190   int ret = widget_instance_pause( mInstanceId.c_str() );
191   if( ret < 0 )
192   {
193     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::PauseWidget: Fail to pause widget(%s, %s) [%d]\n", mWidgetId.c_str(), mInstanceId.c_str(), ret );
194     return false;
195   }
196
197   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::PauseWidget: Widget is paused (%s, %s)\n", mWidgetId.c_str(), mInstanceId.c_str() );
198
199   return true;
200 }
201
202 bool WidgetView::ResumeWidget()
203 {
204   int ret = widget_instance_resume( mInstanceId.c_str() );
205   if( ret < 0 )
206   {
207     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ResumeWidget: Fail to resume widget(%s, %s) [%d]\n", mWidgetId.c_str(), mInstanceId.c_str(), ret );
208     return false;
209   }
210
211   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ResumeWidget: Widget is resumed (%s, %s)\n", mWidgetId.c_str(), mInstanceId.c_str() );
212
213   return true;
214 }
215
216 const std::string& WidgetView::GetWidgetId() const
217 {
218   return mWidgetId;
219 }
220
221 const std::string& WidgetView::GetInstanceId() const
222 {
223   return mInstanceId;
224 }
225
226 const std::string& WidgetView::GetContentInfo()
227 {
228   widget_instance_h instance;
229   char* contentInfo = NULL;
230
231   mContentInfo.clear();
232
233   if( mWidgetId.empty() || mInstanceId.empty() )
234   {
235     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Widget id (%s) or instance id (%s) is invalid.\n", mWidgetId.c_str(), mInstanceId.c_str() );
236     return mContentInfo;
237   }
238
239   instance = widget_instance_get_instance( mWidgetId.c_str(), mInstanceId.c_str() );
240   if( !instance )
241   {
242     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: widget_instance_get_instance is failed. [%s]\n", mInstanceId.c_str() );
243     return mContentInfo;
244   }
245
246   if( widget_instance_get_content( instance, &contentInfo ) < 0 )
247   {
248     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Failed to get content of widget. [%s]\n", mInstanceId.c_str() );
249     return mContentInfo;
250   }
251
252   mContentInfo = reinterpret_cast< char* >( contentInfo );
253
254   return mContentInfo;
255 }
256
257 const std::string& WidgetView::GetTitle()
258 {
259   //ToDo: We should add some codes by considering widget_viewer_evas
260   if( mTitle.empty() )
261   {
262     mTitle = widget_service_get_name( mWidgetId.c_str(), NULL );
263   }
264
265   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetTitle: title = %s\n", mTitle.c_str() );
266
267   return mTitle;
268 }
269
270 double WidgetView::GetUpdatePeriod() const
271 {
272   return mUpdatePeriod;
273 }
274
275 void WidgetView::Show()
276 {
277   if( mWidgetImageView )
278   {
279     mWidgetImageView.SetVisible( true );
280   }
281 }
282
283 void WidgetView::Hide()
284 {
285   if( mWidgetImageView )
286   {
287     mWidgetImageView.SetVisible( false );
288   }
289 }
290
291 bool WidgetView::CancelTouchEvent()
292 {
293   if( mRemoteSurface )
294   {
295     tizen_remote_surface_transfer_touch_cancel( mRemoteSurface );
296     return true;
297   }
298
299   return false;
300 }
301
302 void WidgetView::SetPreviewEnabled( bool enabled )
303 {
304   mPreviewEnabled = enabled;
305
306   if( mPreviewImage )
307   {
308     mPreviewImage.SetVisible( enabled );
309   }
310 }
311
312 bool WidgetView::GetPreviewEnabled() const
313 {
314   return mPreviewEnabled;
315 }
316
317 void WidgetView::SetStateTextEnabled( bool enabled )
318 {
319   mStateTextEnabled = enabled;
320
321   if( mStateText )
322   {
323     mStateText.SetVisible( enabled );
324   }
325 }
326
327 bool WidgetView::GetStateTextEnabled() const
328 {
329   return mStateTextEnabled;
330 }
331
332 void WidgetView::ActivateFaultedWidget()
333 {
334   if( mPid < 0 )
335   {
336     // Esable preview and text
337     if( mPreviewEnabled )
338     {
339       mPreviewImage.SetVisible( true );
340     }
341
342     if( mStateTextEnabled )
343     {
344       mStateText.SetVisible( true );
345     }
346
347     // launch widget again
348     mPid = widget_instance_launch( mInstanceId.c_str(), (char *)mContentInfo.c_str(), mWidth, mHeight );
349     if( mPid < 0)
350     {
351       DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ActivateFaultedWidget: widget_instance_launch is failed. [%s]\n", mWidgetId.c_str() );
352
353       // Emit signal
354       Dali::WidgetView::WidgetView handle( GetOwner() );
355       mWidgetCreationAbortedSignal.Emit( handle );
356
357       return;
358     }
359
360     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ActivateFaultedWidget: widget_instance_launch is called. [%s, mPid = %d]\n", mWidgetId.c_str(), mPid );
361   }
362 }
363
364 bool WidgetView::IsWidgetFaulted()
365 {
366   return mPid < 0 ? true : false;
367 }
368
369 void WidgetView::SetPermanentDelete( bool permanentDelete )
370 {
371   mPermanentDelete = permanentDelete;
372 }
373
374 void WidgetView::CreateWidgetImageView()
375 {
376   Any source;
377   mImageSource = Dali::NativeImageSource::New( source );
378   Dali::NativeImage image = Dali::NativeImage::New( *mImageSource );
379
380   mWidgetImageView = Dali::Toolkit::ImageView::New( image );
381
382   mWidgetImageView.SetParentOrigin( ParentOrigin::CENTER );
383   mWidgetImageView.SetAnchorPoint( AnchorPoint::CENTER );
384   mWidgetImageView.SetSize( mWidth, mHeight );
385
386   Self().Add( mWidgetImageView );
387
388   // Disable preview and text
389   if( mPreviewEnabled )
390   {
391     mPreviewImage.SetVisible( false );
392   }
393
394   if( mStateTextEnabled )
395   {
396     mStateText.SetVisible( false );
397   }
398
399   // Emit signal
400   Dali::WidgetView::WidgetView handle( GetOwner() );
401   mWidgetAddedSignal.Emit( handle );
402
403   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::AddObjectView: ObjectView is added.\n" );
404 }
405
406 void WidgetView::RemoveObjectView()
407 {
408   // Enable preview and text
409   if( mPreviewEnabled )
410   {
411     mPreviewImage.SetVisible( true );
412   }
413
414   if( mStateTextEnabled )
415   {
416     mStateText.SetVisible( true );
417   }
418
419   // Emit signal
420   Dali::WidgetView::WidgetView handle( GetOwner() );
421   mWidgetDeletedSignal.Emit( handle );
422
423   mWidgetImageView.Reset();
424
425   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::RemoveObjectView: ObjectView is removed.\n" );
426 }
427
428 void WidgetView::SendWidgetEvent( int event )
429 {
430   Dali::WidgetView::WidgetView handle( GetOwner() );
431
432   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::SendWidgetEvent: event = %d widget = %s\n", event,  mWidgetId.c_str() );
433
434   // Emit signal
435   switch( event )
436   {
437     case WIDGET_INSTANCE_EVENT_UPDATE:
438     {
439       mWidgetContentUpdatedSignal.Emit( handle );
440       break;
441     }
442     case WIDGET_INSTANCE_EVENT_PERIOD_CHANGED:
443     {
444       mWidgetUpdatePeriodChangedSignal.Emit( handle );
445       break;
446     }
447     case WIDGET_INSTANCE_EVENT_SIZE_CHANGED:
448     {
449       mWidgetResizedSignal.Emit( handle );
450       break;
451     }
452     case WIDGET_INSTANCE_EVENT_EXTRA_UPDATED:
453     {
454       mWidgetExtraInfoUpdatedSignal.Emit( handle );
455       break;
456     }
457     case WIDGET_INSTANCE_EVENT_FAULT:
458     {
459       mWidgetFaultedSignal.Emit( handle );
460       break;
461     }
462     default:
463     {
464       break;
465     }
466   }
467 }
468
469 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetAddedSignal()
470 {
471   return mWidgetAddedSignal;
472 }
473
474 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetDeletedSignal()
475 {
476   return mWidgetDeletedSignal;
477 }
478
479 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetCreationAbortedSignal()
480 {
481   return mWidgetCreationAbortedSignal;
482 }
483
484 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetResizedSignal()
485 {
486   return mWidgetResizedSignal;
487 }
488
489 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetContentUpdatedSignal()
490 {
491   return mWidgetContentUpdatedSignal;
492 }
493
494 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetExtraInfoUpdatedSignal()
495 {
496   return mWidgetExtraInfoUpdatedSignal;
497 }
498
499 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetUpdatePeriodChangedSignal()
500 {
501   return mWidgetUpdatePeriodChangedSignal;
502 }
503
504 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetFaultedSignal()
505 {
506   return mWidgetFaultedSignal;
507 }
508
509 void WidgetView::OnInitialize()
510 {
511   char* instanceId = NULL;
512   char* previewPath = NULL;
513   std::string previewImage;
514   widget_size_type_e sizeType;
515
516   int ret = widget_instance_create( mWidgetId.c_str(), &instanceId );
517   if( ret < 0 || !instanceId )
518   {
519     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_create is failed [%s].\n", mWidgetId.c_str() );
520     return;
521   }
522
523   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_create is called. [widget id = %s, instance id = %s]\n",
524                  mWidgetId.c_str(), instanceId );
525
526   mInstanceId = instanceId;
527
528   // Preview image
529   widget_service_get_size_type( mWidth, mHeight, &sizeType );
530
531   previewPath = widget_service_get_preview_image_path( mWidgetId.c_str(), sizeType );
532   if( previewPath )
533   {
534     previewImage = previewPath;
535     free( previewPath );
536   }
537   else
538   {
539     previewImage = tzplatform_getenv( TZ_SYS_SHARE );
540     previewImage.append( WIDGET_VIEW_RESOURCE_DEFAULT_IMG );
541   }
542
543   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: preview image path = %s\n", previewImage.c_str() );
544
545   mPreviewImage = Toolkit::ImageView::New( previewImage );
546
547   mPreviewImage.SetParentOrigin( ParentOrigin::CENTER );
548   mPreviewImage.SetAnchorPoint( AnchorPoint::CENTER );
549
550   if( !previewPath )
551   {
552     mPreviewImage.SetSize( mWidth, mHeight );
553   }
554
555   Self().SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
556   Self().Add( mPreviewImage );
557
558   // State text
559   // TODO: use po files
560   mStateText = Toolkit::TextLabel::New( "Loading..." );
561
562   mStateText.SetParentOrigin( ParentOrigin::CENTER );
563   mStateText.SetAnchorPoint( AnchorPoint::CENTER );
564   mStateText.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
565   mStateText.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
566
567   mPreviewImage.Add( mStateText );
568
569   // launch widget
570   mPid = widget_instance_launch( instanceId, (char *)mContentInfo.c_str(), mWidth, mHeight );
571   if( mPid < 0)
572   {
573     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_launch is failed. [%s]\n", mWidgetId.c_str() );
574
575     // Emit signal
576     Dali::WidgetView::WidgetView handle( GetOwner() );
577     mWidgetCreationAbortedSignal.Emit( handle );
578
579     return;
580   }
581
582   aul_rsm_viewer_set_surface_handler( mInstanceId.c_str(), &remoteSurfaceHandler, this );
583
584   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_launch is called. [%s, mPid = %d]\n", mWidgetId.c_str(), mPid );
585
586 }
587
588 void WidgetView::OnSizeSet( const Vector3& targetSize )
589 {
590   if( mWidgetImageView )
591   {
592     mWidgetImageView.SetSize( targetSize );
593   }
594 }
595
596 bool WidgetView::IsWidgetImageView()
597 {
598   return ( mWidgetImageView )? true: false;
599 }
600
601 void WidgetView::UpdateImageSource( tbm_surface_h source )
602 {
603   mImageSource->SetSource( source );
604   Dali::Stage::GetCurrent().KeepRendering( 0.0f );
605 }
606
607 void WidgetView::ConnectSignal( tizen_remote_surface* surface )
608 {
609   if( mWidgetImageView )
610   {
611     mRemoteSurface = surface;
612     mWidgetImageView.TouchSignal().Connect( this, &WidgetView::OnTouch );
613     mWidgetImageView.WheelEventSignal().Connect( this, &WidgetView::OnWheelEvent );
614   }
615
616 }
617
618 bool WidgetView::OnTouch( Dali::Actor actor, const Dali::TouchData& event )
619 {
620   tizen_remote_surface_event_type type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_NONE;
621
622   switch( event.GetState( 0 ) )
623   {
624     case Dali::PointState::UP:
625     {
626       type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_UP;
627       break;
628     }
629     case Dali::PointState::DOWN:
630     {
631       type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_DOWN;
632       break;
633     }
634     case Dali::PointState::MOTION:
635     {
636       type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_MOVE;
637       break;
638     }
639     default:
640     {
641       return false;
642     }
643   }
644
645   tizen_remote_surface_transfer_mouse_event( mRemoteSurface,
646                                              type,
647                                              event.GetDeviceId( 0 ),
648                                              1,
649                                              event.GetLocalPosition( 0 ).x,
650                                              event.GetLocalPosition( 0 ).y,
651                                              event.GetEllipseRadius( 0 ).x,
652                                              event.GetEllipseRadius( 0 ).y,
653                                              event.GetPressure( 0 ),
654                                              event.GetAngle( 0 ).degree,
655                                              TIZEN_INPUT_DEVICE_CLAS_MOUSE,
656                                              TIZEN_INPUT_DEVICE_SUBCLAS_NONE,
657                                              "",
658                                              event.GetTime()
659                                            );
660   return true;
661 }
662
663 bool WidgetView::OnWheelEvent( Dali::Actor actor, const Dali::WheelEvent& event )
664 {
665   tizen_remote_surface_transfer_mouse_wheel( mRemoteSurface,
666                                              event.direction,
667                                              event.z,
668                                              TIZEN_INPUT_DEVICE_CLAS_MOUSE,
669                                              TIZEN_INPUT_DEVICE_SUBCLAS_NONE,
670                                              "",
671                                              event.timeStamp
672                                            );
673   return true;
674 }
675
676 } // namespace Internal
677
678 } // namespace WidgetView
679
680 } // namespace Dali