Merge "spec fix: version check error" into tizen
[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   Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
241
242   mIndicatorVisible = visibleMode;
243
244   if ( mIndicatorVisible == Dali::Window::VISIBLE )
245   {
246     // when the indicator is visible, set proper mode for indicator server according to bg mode
247     if ( mIndicatorOpacityMode == Dali::Window::OPAQUE )
248     {
249       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
250     }
251     else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT )
252     {
253       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSLUCENT);
254     }
255     else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT )
256     {
257       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
258     }
259   }
260   else
261   {
262     // when the indicator is not visible, set TRANSPARENT mode for indicator server
263     ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSPARENT); // it means hidden indicator
264   }
265
266   DoShowIndicator( mIndicatorOrientation );
267 }
268
269 void Window::RotateIndicator( Dali::Window::WindowOrientation orientation )
270 {
271   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation );
272
273   DoRotateIndicator( orientation );
274 }
275
276 void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode )
277 {
278   mIndicatorOpacityMode = opacityMode;
279
280   if( mIndicator != NULL )
281   {
282     mIndicator->SetOpacityMode( opacityMode );
283   }
284 }
285
286 void Window::SetClass(std::string name, std::string klass)
287 {
288   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
289
290   if( wlSurface )
291   {
292     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
293     ecore_wl_window_title_set( wlWindow, name.c_str() );
294     ecore_wl_window_class_name_set( wlWindow, klass.c_str() );
295   }
296   else
297   {
298     DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window has no surface\n" );
299   }
300 }
301
302 Window::Window()
303 : mSurface( NULL ),
304   mIndicatorVisible( Dali::Window::VISIBLE ),
305   mIndicatorIsShown( false ),
306   mShowRotatedIndicatorOnClose( false ),
307   mStarted( false ),
308   mIsTransparent( false ),
309   mWMRotationAppSet( false ),
310   mEcoreEventHander( true ),
311   mIsFocusAcceptable( true ),
312   mIndicator( NULL ),
313   mIndicatorOrientation( Dali::Window::PORTRAIT ),
314   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
315   mIndicatorOpacityMode( Dali::Window::OPAQUE ),
316   mOverlay( NULL ),
317   mAdaptor( NULL ),
318   mEventHandler( NULL ),
319   mPreferredOrientation( Dali::Window::PORTRAIT )
320 {
321 }
322
323 Window::~Window()
324 {
325   delete mEventHandler;
326
327   if( mIndicator )
328   {
329     mIndicator->Close();
330     delete mIndicator;
331   }
332
333   if ( mAdaptor )
334   {
335     mAdaptor->RemoveObserver( *this );
336     mAdaptor->SetDragAndDropDetector( NULL );
337     mAdaptor = NULL;
338   }
339
340   delete mSurface;
341 }
342
343 void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
344 {
345   // create an Wayland window by default
346   Any surface;
347   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, mIsTransparent );
348
349   mSurface = windowSurface;
350   SetClass( name, className );
351   windowSurface->Map();
352
353   mOrientation = Orientation::New(this);
354
355   // create event handler for Wayland window
356   mEventHandler = new EventHandler( this );
357 }
358
359 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
360 {
361   if( mIndicator == NULL )
362   {
363     if( mIndicatorVisible != Dali::Window::INVISIBLE )
364     {
365       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
366       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
367       Dali::Actor actor = mIndicator->GetActor();
368       SetIndicatorActorRotation();
369       mOverlay->Add(actor);
370     }
371     // else don't create a hidden indicator
372   }
373   else // Already have indicator
374   {
375     if( mIndicatorVisible == Dali::Window::VISIBLE )
376     {
377       // If we are resuming, and rotation has changed,
378       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
379       {
380         // then close current indicator and open new one
381         mShowRotatedIndicatorOnClose = true;
382         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
383         // Don't show actor - will contain indicator for old orientation.
384       }
385     }
386   }
387
388   // set indicator visible mode
389   if( mIndicator != NULL )
390   {
391     mIndicator->SetVisible( mIndicatorVisible );
392   }
393
394   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
395   SetIndicatorProperties( show, lastOrientation );
396   mIndicatorIsShown = show;
397 }
398
399 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
400 {
401   if( mIndicatorIsShown )
402   {
403     mShowRotatedIndicatorOnClose = true;
404     mNextIndicatorOrientation = orientation;
405     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
406   }
407   else
408   {
409     // Save orientation for when the indicator is next shown
410     mShowRotatedIndicatorOnClose = false;
411     mNextIndicatorOrientation = orientation;
412   }
413 }
414
415 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
416 {
417   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
418
419   if( wlSurface )
420   {
421     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
422     if ( isShow )
423     {
424       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_ON);
425     }
426     else
427     {
428       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_OFF);
429     }
430   }
431 }
432
433 void Window::IndicatorTypeChanged(Indicator::Type type)
434 {
435 #if defined(DALI_PROFILE_MOBILE)
436   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
437
438   if( wlSurface )
439   {
440     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
441     switch(type)
442     {
443       case Indicator::INDICATOR_TYPE_1:
444         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
445         break;
446
447       case Indicator::INDICATOR_TYPE_2:
448         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
449         break;
450
451       case Indicator::INDICATOR_TYPE_UNKNOWN:
452       default:
453         break;
454     }
455   }
456 #endif //MOBILE
457 }
458
459 void Window::IndicatorClosed( IndicatorInterface* indicator )
460 {
461   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
462
463   if( mShowRotatedIndicatorOnClose )
464   {
465     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
466     mIndicator->Open(mNextIndicatorOrientation);
467     mIndicatorOrientation = mNextIndicatorOrientation;
468     SetIndicatorActorRotation();
469     DoShowIndicator(currentOrientation);
470   }
471 }
472
473 void Window::IndicatorVisibilityChanged(bool isVisible)
474 {
475   mIndicatorVisibilityChangedSignal.Emit(isVisible);
476 }
477
478 void Window::SetIndicatorActorRotation()
479 {
480   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
481   DALI_ASSERT_DEBUG( mIndicator != NULL );
482
483   Dali::Actor actor = mIndicator->GetActor();
484   switch( mIndicatorOrientation )
485   {
486     case Dali::Window::PORTRAIT:
487       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
488       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
489       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
490       break;
491     case Dali::Window::PORTRAIT_INVERSE:
492       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
493       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
494       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
495       break;
496     case Dali::Window::LANDSCAPE:
497       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
498       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
499       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
500       break;
501     case Dali::Window::LANDSCAPE_INVERSE:
502       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
503       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
504       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
505       break;
506   }
507 }
508
509 void Window::Raise()
510 {
511   ecore_wl_window_raise( mEventHandler->mEcoreWindow );
512 }
513
514 void Window::Lower()
515 {
516   ecore_wl_window_lower( mEventHandler->mEcoreWindow );
517 }
518
519 void Window::Activate()
520 {
521   ecore_wl_window_activate( mEventHandler->mEcoreWindow );
522 }
523
524 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
525 {
526   return mDragAndDropDetector;
527 }
528
529 Dali::Any Window::GetNativeHandle() const
530 {
531   if(mEventHandler)
532   {
533     return mEventHandler->mEcoreWindow;
534   }
535   else
536   {
537     return Dali::Any();
538   }
539 }
540
541 void Window::OnStart()
542 {
543   DoShowIndicator( mIndicatorOrientation );
544 }
545
546 void Window::OnPause()
547 {
548 }
549
550 void Window::OnResume()
551 {
552   // resume indicator status
553   if( mIndicator != NULL )
554   {
555     // Restore own indicator opacity
556     // Send opacity mode to indicator service when app resumed
557     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
558   }
559 }
560
561 void Window::OnStop()
562 {
563   if( mIndicator )
564   {
565     mIndicator->Close();
566   }
567
568   delete mIndicator;
569   mIndicator = NULL;
570 }
571
572 void Window::OnDestroy()
573 {
574   mAdaptor = NULL;
575 }
576
577 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
578 {
579   bool found = false;
580
581   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
582   {
583     if(mAvailableOrientations[i] == orientation)
584     {
585       found = true;
586       break;
587     }
588   }
589
590   if( ! found )
591   {
592     mAvailableOrientations.push_back(orientation);
593     SetAvailableOrientations( mAvailableOrientations );
594   }
595 }
596
597 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
598 {
599   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
600        iter != mAvailableOrientations.end(); ++iter )
601   {
602     if( *iter == orientation )
603     {
604       mAvailableOrientations.erase( iter );
605       break;
606     }
607   }
608   SetAvailableOrientations( mAvailableOrientations );
609 }
610
611 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
612 {
613   int rotations[4];
614   for( std::size_t i = 0; i < mAvailableOrientations.size(); ++i )
615   {
616     rotations[i] = static_cast< int >( mAvailableOrientations[i] );
617   }
618   ecore_wl_window_rotation_available_rotations_set( mEventHandler->mEcoreWindow, rotations, mAvailableOrientations.size() );
619 }
620
621 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
622 {
623   return mAvailableOrientations;
624 }
625
626 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
627 {
628   mPreferredOrientation = orientation;
629
630   ecore_wl_window_rotation_preferred_rotation_set( mEventHandler->mEcoreWindow, orientation );
631 }
632
633 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
634 {
635   return mPreferredOrientation;
636 }
637
638 void Window::SetAcceptFocus( bool accept )
639 {
640   mIsFocusAcceptable = accept;
641
642   ecore_wl_window_focus_skip_set( mEventHandler->mEcoreWindow, !accept );
643 }
644
645 bool Window::IsFocusAcceptable()
646 {
647   return mIsFocusAcceptable;
648 }
649
650 void Window::RotationDone( int orientation, int width, int height )
651 {
652   ecore_wl_window_rotation_change_done_send( mEventHandler->mEcoreWindow );
653 }
654
655 } // Adaptor
656 } // Internal
657 } // Dali