Merge "Remove duplicated implementation of IMF Manager" into devel/master
[platform/core/uifw/dali-adaptor.git] / adaptors / ecore / wayland / window-impl-ecore-wl.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <window-impl.h>
20
21 // EXTERNAL HEADERS
22 #include <Ecore.h>
23 #include <Ecore_Wayland.h>
24
25 #include <dali/integration-api/core.h>
26 #include <dali/integration-api/system-overlay.h>
27 #include <dali/public-api/render-tasks/render-task.h>
28 #include <dali/public-api/render-tasks/render-task-list.h>
29 #include <orientation.h>
30
31 // INTERNAL HEADERS
32 #include <window-render-surface.h>
33 #include <drag-and-drop-detector-impl.h>
34 #include <ecore-indicator-impl.h>
35 #include <window-visibility-observer.h>
36 #include <orientation-impl.h>
37
38 namespace
39 {
40 const float INDICATOR_ANIMATION_DURATION( 0.18f ); // 180 milli seconds
41 const float INDICATOR_SHOW_Y_POSITION( 0.0f );
42 const float INDICATOR_HIDE_Y_POSITION( -52.0f );
43 }
44
45 namespace Dali
46 {
47 namespace Internal
48 {
49 namespace Adaptor
50 {
51 #if defined(DEBUG_ENABLED)
52 Debug::Filter* gWindowLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_WINDOW");
53 #endif
54
55 /**
56  * TODO: Abstract Window class out and move this into a window implementation for Ecore
57  */
58 struct Window::EventHandler
59 {
60   /**
61    * Constructor
62    * @param[in]  window  A pointer to the window class.
63    */
64   EventHandler( Window* window )
65   : mWindow( window ),
66     mWindowPropertyHandler( NULL ),
67     mWindowIconifyStateHandler( NULL ),
68     mWindowFocusInHandler( NULL ),
69     mWindowFocusOutHandler( NULL ),
70     mEcoreWindow( 0 )
71   {
72     // store ecore window handle
73     ECore::WindowRenderSurface* wlWindow( dynamic_cast< ECore::WindowRenderSurface * >( mWindow->mSurface ) );
74     if( wlWindow )
75     {
76       mEcoreWindow = wlWindow->GetWlWindow();
77     }
78     DALI_ASSERT_ALWAYS( mEcoreWindow != 0 && "There is no ecore Wl window");
79
80     if( mWindow->mEcoreEventHander )
81     {
82       mWindowIconifyStateHandler = ecore_event_handler_add( ECORE_WL_EVENT_WINDOW_ICONIFY_STATE_CHANGE, EcoreEventWindowIconifyStateChanged, this );
83       mWindowFocusInHandler = ecore_event_handler_add( ECORE_WL_EVENT_FOCUS_IN, EcoreEventWindowFocusIn, this );
84       mWindowFocusOutHandler = ecore_event_handler_add( ECORE_WL_EVENT_FOCUS_OUT, EcoreEventWindowFocusOut, this );
85     }
86   }
87
88   /**
89    * Destructor
90    */
91   ~EventHandler()
92   {
93     if ( mWindowPropertyHandler )
94     {
95       ecore_event_handler_del( mWindowPropertyHandler );
96     }
97     if ( mWindowIconifyStateHandler )
98     {
99       ecore_event_handler_del( mWindowIconifyStateHandler );
100     }
101     if( mWindowFocusInHandler )
102     {
103       ecore_event_handler_del( mWindowFocusInHandler );
104     }
105     if( mWindowFocusOutHandler )
106     {
107       ecore_event_handler_del( mWindowFocusOutHandler );
108     }
109   }
110
111   // Static methods
112
113   /// Called when the window properties are changed.
114   static Eina_Bool EcoreEventWindowPropertyChanged( void* data, int type, void* event )
115   {
116     return EINA_FALSE;
117   }
118
119   /// Called when the window iconify state is changed.
120   static Eina_Bool EcoreEventWindowIconifyStateChanged( void* data, int type, void* event )
121   {
122     Ecore_Wl_Event_Window_Iconify_State_Change* iconifyChangedEvent( static_cast< Ecore_Wl_Event_Window_Iconify_State_Change* >( event ) );
123     EventHandler* handler( static_cast< EventHandler* >( data ) );
124     Eina_Bool handled( ECORE_CALLBACK_PASS_ON );
125
126     if ( handler && handler->mWindow )
127     {
128       WindowVisibilityObserver* observer( handler->mWindow->mAdaptor );
129       if ( observer && ( iconifyChangedEvent->win == static_cast< unsigned int> ( ecore_wl_window_id_get( handler->mEcoreWindow ) ) ) )
130       {
131         if( iconifyChangedEvent->iconified == EINA_TRUE )
132         {
133           observer->OnWindowHidden();
134           DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Iconfied\n", handler->mEcoreWindow );
135         }
136         else
137         {
138           observer->OnWindowShown();
139           DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Shown\n", handler->mEcoreWindow );
140         }
141         handled = ECORE_CALLBACK_DONE;
142       }
143     }
144
145     return handled;
146   }
147
148   /// Called when the window gains focus
149   static Eina_Bool EcoreEventWindowFocusIn( void* data, int type, void* event )
150   {
151     Ecore_Wl_Event_Focus_In* focusInEvent( static_cast< Ecore_Wl_Event_Focus_In* >( event ) );
152     EventHandler* handler( static_cast< EventHandler* >( data ) );
153
154     if ( handler && handler->mWindow && focusInEvent->win == static_cast< unsigned int >( ecore_wl_window_id_get( handler->mEcoreWindow ) ) )
155     {
156       DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window EcoreEventWindowFocusIn\n" );
157
158       handler->mWindow->mFocusChangedSignal.Emit( true );
159     }
160
161     return ECORE_CALLBACK_PASS_ON;
162   }
163
164   /// Called when the window loses focus
165   static Eina_Bool EcoreEventWindowFocusOut( void* data, int type, void* event )
166   {
167     Ecore_Wl_Event_Focus_Out* focusOutEvent( static_cast< Ecore_Wl_Event_Focus_Out* >( event ) );
168     EventHandler* handler( static_cast< EventHandler* >( data ) );
169
170     if ( handler && handler->mWindow && focusOutEvent->win == static_cast< unsigned int >(ecore_wl_window_id_get( handler->mEcoreWindow ) ) )
171     {
172       DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window EcoreEventWindowFocusOut\n" );
173
174       handler->mWindow->mFocusChangedSignal.Emit( false );
175     }
176
177     return ECORE_CALLBACK_PASS_ON;
178   }
179
180   // Data
181   Window* mWindow;
182   Ecore_Event_Handler* mWindowPropertyHandler;
183   Ecore_Event_Handler* mWindowIconifyStateHandler;
184   Ecore_Event_Handler* mWindowFocusInHandler;
185   Ecore_Event_Handler* mWindowFocusOutHandler;
186   Ecore_Wl_Window* mEcoreWindow;
187 };
188
189 Window* Window::New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent)
190 {
191   Window* window = new Window();
192   window->mIsTransparent = isTransparent;
193   window->Initialize(posSize, name, className);
194   return window;
195 }
196
197 void Window::SetAdaptor(Dali::Adaptor& adaptor)
198 {
199   DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" );
200   mStarted = true;
201
202   // Only create one overlay per window
203   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
204   Integration::Core& core = adaptorImpl.GetCore();
205   mOverlay = &core.GetSystemOverlay();
206
207   Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
208   taskList.CreateTask();
209
210   mAdaptor = &adaptorImpl;
211   mAdaptor->AddObserver( *this );
212
213   // Can only create the detector when we know the Core has been instantiated.
214   mDragAndDropDetector = DragAndDropDetector::New();
215   mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) );
216
217   if( mOrientation )
218   {
219     mOrientation->SetAdaptor(adaptor);
220   }
221
222   if( mIndicator != NULL )
223   {
224     mIndicator->SetAdaptor(mAdaptor);
225   }
226 }
227
228 RenderSurface* Window::GetSurface()
229 {
230   return mSurface;
231 }
232
233 void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode )
234 {
235   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode );
236   DALI_ASSERT_DEBUG(mOverlay);
237
238   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
239   DALI_ASSERT_DEBUG(wlSurface);
240
241   if( wlSurface )
242   {
243     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
244
245     mIndicatorVisible = visibleMode;
246
247     if ( mIndicatorVisible == Dali::Window::VISIBLE )
248     {
249       // when the indicator is visible, set proper mode for indicator server according to bg mode
250       if ( mIndicatorOpacityMode == Dali::Window::OPAQUE )
251       {
252         ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
253       }
254       else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT )
255       {
256         ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSLUCENT);
257       }
258       else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT )
259       {
260         ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
261       }
262     }
263     else
264     {
265       // when the indicator is not visible, set TRANSPARENT mode for indicator server
266       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSPARENT); // it means hidden indicator
267     }
268   }
269
270   DoShowIndicator( mIndicatorOrientation );
271 }
272
273 void Window::RotateIndicator( Dali::Window::WindowOrientation orientation )
274 {
275   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation );
276
277   DoRotateIndicator( orientation );
278 }
279
280 void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode )
281 {
282   mIndicatorOpacityMode = opacityMode;
283
284   if( mIndicator != NULL )
285   {
286     mIndicator->SetOpacityMode( opacityMode );
287   }
288 }
289
290 void Window::SetClass(std::string name, std::string klass)
291 {
292   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
293
294   if( wlSurface )
295   {
296     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
297     ecore_wl_window_title_set( wlWindow, name.c_str() );
298     ecore_wl_window_class_name_set( wlWindow, klass.c_str() );
299   }
300   else
301   {
302     DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window has no surface\n" );
303   }
304 }
305
306 Window::Window()
307 : mSurface( NULL ),
308   mIndicatorVisible( Dali::Window::VISIBLE ),
309   mIndicatorIsShown( false ),
310   mShowRotatedIndicatorOnClose( false ),
311   mStarted( false ),
312   mIsTransparent( false ),
313   mWMRotationAppSet( false ),
314   mEcoreEventHander( true ),
315   mIsFocusAcceptable( true ),
316   mVisible( true ),
317   mIndicator( NULL ),
318   mIndicatorOrientation( Dali::Window::PORTRAIT ),
319   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
320   mIndicatorOpacityMode( Dali::Window::OPAQUE ),
321   mOverlay( NULL ),
322   mAdaptor( NULL ),
323   mEventHandler( NULL ),
324   mPreferredOrientation( Dali::Window::PORTRAIT )
325 {
326 }
327
328 Window::~Window()
329 {
330   delete mEventHandler;
331
332   if( mIndicator )
333   {
334     mIndicator->Close();
335     delete mIndicator;
336   }
337
338   if ( mAdaptor )
339   {
340     mAdaptor->RemoveObserver( *this );
341     mAdaptor->SetDragAndDropDetector( NULL );
342     mAdaptor = NULL;
343   }
344
345   delete mSurface;
346 }
347
348 void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
349 {
350   // create an Wayland window by default
351   Any surface;
352   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, mIsTransparent );
353
354   mSurface = windowSurface;
355   SetClass( name, className );
356   windowSurface->Map();
357
358   mOrientation = Orientation::New(this);
359
360   // create event handler for Wayland window
361   mEventHandler = new EventHandler( this );
362 }
363
364 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
365 {
366   if( mIndicator == NULL )
367   {
368     if( mIndicatorVisible != Dali::Window::INVISIBLE )
369     {
370       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
371       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
372       Dali::Actor actor = mIndicator->GetActor();
373       SetIndicatorActorRotation();
374       mOverlay->Add(actor);
375     }
376     // else don't create a hidden indicator
377   }
378   else // Already have indicator
379   {
380     if( mIndicatorVisible == Dali::Window::VISIBLE )
381     {
382       // If we are resuming, and rotation has changed,
383       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
384       {
385         // then close current indicator and open new one
386         mShowRotatedIndicatorOnClose = true;
387         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
388         // Don't show actor - will contain indicator for old orientation.
389       }
390     }
391   }
392
393   // set indicator visible mode
394   if( mIndicator != NULL )
395   {
396     mIndicator->SetVisible( mIndicatorVisible );
397   }
398
399   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
400   SetIndicatorProperties( show, lastOrientation );
401   mIndicatorIsShown = show;
402 }
403
404 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
405 {
406   if( mIndicatorIsShown )
407   {
408     mShowRotatedIndicatorOnClose = true;
409     mNextIndicatorOrientation = orientation;
410     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
411   }
412   else
413   {
414     // Save orientation for when the indicator is next shown
415     mShowRotatedIndicatorOnClose = false;
416     mNextIndicatorOrientation = orientation;
417   }
418 }
419
420 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
421 {
422   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
423
424   if( wlSurface )
425   {
426     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
427     if ( isShow )
428     {
429       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_ON);
430     }
431     else
432     {
433       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_OFF);
434     }
435   }
436 }
437
438 void Window::IndicatorTypeChanged(Indicator::Type type)
439 {
440 #if defined(DALI_PROFILE_MOBILE)
441   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
442
443   if( wlSurface )
444   {
445     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
446     switch(type)
447     {
448       case Indicator::INDICATOR_TYPE_1:
449         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
450         break;
451
452       case Indicator::INDICATOR_TYPE_2:
453         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
454         break;
455
456       case Indicator::INDICATOR_TYPE_UNKNOWN:
457       default:
458         break;
459     }
460   }
461 #endif //MOBILE
462 }
463
464 void Window::IndicatorClosed( IndicatorInterface* indicator )
465 {
466   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
467
468   if( mShowRotatedIndicatorOnClose )
469   {
470     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
471     mIndicator->Open(mNextIndicatorOrientation);
472     mIndicatorOrientation = mNextIndicatorOrientation;
473     SetIndicatorActorRotation();
474     DoShowIndicator(currentOrientation);
475   }
476 }
477
478 void Window::IndicatorVisibilityChanged(bool isVisible)
479 {
480   mIndicatorVisibilityChangedSignal.Emit(isVisible);
481 }
482
483 void Window::SetIndicatorActorRotation()
484 {
485   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
486   DALI_ASSERT_DEBUG( mIndicator != NULL );
487
488   Dali::Actor actor = mIndicator->GetActor();
489   switch( mIndicatorOrientation )
490   {
491     case Dali::Window::PORTRAIT:
492       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
493       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
494       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
495       break;
496     case Dali::Window::PORTRAIT_INVERSE:
497       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
498       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
499       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
500       break;
501     case Dali::Window::LANDSCAPE:
502       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
503       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
504       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
505       break;
506     case Dali::Window::LANDSCAPE_INVERSE:
507       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
508       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
509       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
510       break;
511   }
512 }
513
514 void Window::Raise()
515 {
516   ecore_wl_window_raise( mEventHandler->mEcoreWindow );
517 }
518
519 void Window::Lower()
520 {
521   ecore_wl_window_lower( mEventHandler->mEcoreWindow );
522 }
523
524 void Window::Activate()
525 {
526   ecore_wl_window_activate( mEventHandler->mEcoreWindow );
527 }
528
529 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
530 {
531   return mDragAndDropDetector;
532 }
533
534 Dali::Any Window::GetNativeHandle() const
535 {
536   if(mEventHandler)
537   {
538     return mEventHandler->mEcoreWindow;
539   }
540   else
541   {
542     return Dali::Any();
543   }
544 }
545
546 void Window::OnStart()
547 {
548   DoShowIndicator( mIndicatorOrientation );
549 }
550
551 void Window::OnPause()
552 {
553 }
554
555 void Window::OnResume()
556 {
557   // resume indicator status
558   if( mIndicator != NULL )
559   {
560     // Restore own indicator opacity
561     // Send opacity mode to indicator service when app resumed
562     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
563   }
564 }
565
566 void Window::OnStop()
567 {
568   if( mIndicator )
569   {
570     mIndicator->Close();
571   }
572
573   delete mIndicator;
574   mIndicator = NULL;
575 }
576
577 void Window::OnDestroy()
578 {
579   mAdaptor = NULL;
580 }
581
582 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
583 {
584   bool found = false;
585
586   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
587   {
588     if(mAvailableOrientations[i] == orientation)
589     {
590       found = true;
591       break;
592     }
593   }
594
595   if( ! found )
596   {
597     mAvailableOrientations.push_back(orientation);
598     SetAvailableOrientations( mAvailableOrientations );
599   }
600 }
601
602 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
603 {
604   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
605        iter != mAvailableOrientations.end(); ++iter )
606   {
607     if( *iter == orientation )
608     {
609       mAvailableOrientations.erase( iter );
610       break;
611     }
612   }
613   SetAvailableOrientations( mAvailableOrientations );
614 }
615
616 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
617 {
618   int rotations[4];
619   for( std::size_t i = 0; i < mAvailableOrientations.size(); ++i )
620   {
621     rotations[i] = static_cast< int >( mAvailableOrientations[i] );
622   }
623   ecore_wl_window_rotation_available_rotations_set( mEventHandler->mEcoreWindow, rotations, mAvailableOrientations.size() );
624 }
625
626 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
627 {
628   return mAvailableOrientations;
629 }
630
631 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
632 {
633   mPreferredOrientation = orientation;
634
635   ecore_wl_window_rotation_preferred_rotation_set( mEventHandler->mEcoreWindow, orientation );
636 }
637
638 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
639 {
640   return mPreferredOrientation;
641 }
642
643 void Window::SetAcceptFocus( bool accept )
644 {
645   mIsFocusAcceptable = accept;
646
647   ecore_wl_window_focus_skip_set( mEventHandler->mEcoreWindow, !accept );
648 }
649
650 bool Window::IsFocusAcceptable()
651 {
652   return mIsFocusAcceptable;
653 }
654
655 void Window::Show()
656 {
657   mVisible = true;
658   ecore_wl_window_show( mEventHandler->mEcoreWindow );
659
660   // Need an update request
661   if( mAdaptor )
662   {
663     mAdaptor->RequestUpdateOnce();
664   }
665 }
666
667 void Window::Hide()
668 {
669   mVisible = false;
670   ecore_wl_window_hide( mEventHandler->mEcoreWindow );
671 }
672
673 bool Window::IsVisible() const
674 {
675   return mVisible;
676 }
677
678 void Window::RotationDone( int orientation, int width, int height )
679 {
680   ecore_wl_window_rotation_change_done_send( mEventHandler->mEcoreWindow );
681 }
682
683 } // Adaptor
684 } // Internal
685 } // Dali