[3.0] Support screen rotation
[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     mEcoreEventHandler(),
67     mEcoreWindow( 0 )
68   {
69     // store ecore window handle
70     ECore::WindowRenderSurface* wlWindow( dynamic_cast< ECore::WindowRenderSurface * >( mWindow->mSurface ) );
71     if( wlWindow )
72     {
73       mEcoreWindow = wlWindow->GetWlWindow();
74     }
75     DALI_ASSERT_ALWAYS( mEcoreWindow != 0 && "There is no ecore Wl window");
76
77 #ifndef DALI_PROFILE_UBUNTU
78     if( mWindow->mEcoreEventHander )
79     {
80       mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL_EVENT_WINDOW_ICONIFY_STATE_CHANGE, EcoreEventWindowIconifyStateChanged, this ) );
81       mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL_EVENT_OUTPUT_TRANSFORM, EcoreEventOutputTransform, this) );
82       mEcoreEventHandler.PushBack( ecore_event_handler_add( ECORE_WL_EVENT_IGNORE_OUTPUT_TRANSFORM, EcoreEventIgnoreOutputTransform, this) );
83     }
84 #endif
85
86   }
87
88   /**
89    * Destructor
90    */
91   ~EventHandler()
92   {
93     for( Dali::Vector< Ecore_Event_Handler* >::Iterator iter = mEcoreEventHandler.Begin(), endIter = mEcoreEventHandler.End(); iter != endIter; ++iter )
94     {
95       ecore_event_handler_del( *iter );
96     }
97     mEcoreEventHandler.Clear();
98   }
99
100   // Static methods
101
102 #ifndef DALI_PROFILE_UBUNTU
103   /// Called when the window iconify state is changed.
104   static Eina_Bool EcoreEventWindowIconifyStateChanged( void* data, int type, void* event )
105   {
106     Ecore_Wl_Event_Window_Iconify_State_Change* iconifyChangedEvent( static_cast< Ecore_Wl_Event_Window_Iconify_State_Change* >( event ) );
107     EventHandler* handler( static_cast< EventHandler* >( data ) );
108     Eina_Bool handled( ECORE_CALLBACK_PASS_ON );
109
110     if ( handler && handler->mWindow )
111     {
112       WindowVisibilityObserver* observer( handler->mWindow->mAdaptor );
113       if ( observer && ( iconifyChangedEvent->win == static_cast< unsigned int> ( ecore_wl_window_id_get( handler->mEcoreWindow ) ) ) )
114       {
115         if( iconifyChangedEvent->iconified == EINA_TRUE )
116         {
117           observer->OnWindowHidden();
118           DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Iconfied\n", handler->mEcoreWindow );
119         }
120         else
121         {
122           observer->OnWindowShown();
123           DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Shown\n", handler->mEcoreWindow );
124         }
125         handled = ECORE_CALLBACK_DONE;
126       }
127     }
128
129     return handled;
130   }
131
132   /// Called when the output is transformed
133   static Eina_Bool EcoreEventOutputTransform( void* data, int type, void* event )
134   {
135     Ecore_Wl_Event_Output_Transform* transformEvent( static_cast< Ecore_Wl_Event_Output_Transform* >( event ) );
136     EventHandler* handler( static_cast< EventHandler* >( data ) );
137
138     if ( handler && handler->mWindow && transformEvent->output == ecore_wl_window_output_find( handler->mEcoreWindow ) )
139     {
140       DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) EcoreEventOutputTransform\n", handler->mEcoreWindow );
141
142       ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( handler->mWindow->mSurface ) );
143       if( wlSurface )
144       {
145         wlSurface->OutputTransformed();
146
147         PositionSize positionSize = wlSurface->GetPositionSize();
148         handler->mWindow->mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
149         handler->mWindow->mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
150       }
151     }
152
153     return ECORE_CALLBACK_PASS_ON;
154   }
155
156   /// Called when the output transform should be ignored
157   static Eina_Bool EcoreEventIgnoreOutputTransform( void* data, int type, void* event )
158   {
159     Ecore_Wl_Event_Ignore_Output_Transform* ignoreTransformEvent( static_cast< Ecore_Wl_Event_Ignore_Output_Transform* >( event ) );
160     EventHandler* handler( static_cast< EventHandler* >( data ) );
161
162     if ( handler && handler->mWindow && ignoreTransformEvent->win == handler->mEcoreWindow )
163     {
164       DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) EcoreEventIgnoreOutputTransform\n", handler->mEcoreWindow );
165
166       ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( handler->mWindow->mSurface ) );
167       if( wlSurface )
168       {
169         wlSurface->OutputTransformed();
170
171         PositionSize positionSize = wlSurface->GetPositionSize();
172         handler->mWindow->mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
173         handler->mWindow->mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
174       }
175     }
176
177     return ECORE_CALLBACK_PASS_ON;
178   }
179 #endif
180
181   // Data
182   Window* mWindow;
183   Dali::Vector< Ecore_Event_Handler* > mEcoreEventHandler;
184   Ecore_Wl_Window* mEcoreWindow;
185 };
186
187
188 Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
189 {
190   Window* window = new Window();
191   window->mIsTransparent = isTransparent;
192   window->Initialize( positionSize, name, className );
193   return window;
194 }
195
196 void Window::SetAdaptor(Dali::Adaptor& adaptor)
197 {
198   DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" );
199   mStarted = true;
200
201   // Only create one overlay per window
202   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
203   Integration::Core& core = adaptorImpl.GetCore();
204   mOverlay = &core.GetSystemOverlay();
205
206   Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
207   taskList.CreateTask();
208
209   mAdaptor = &adaptorImpl;
210   mAdaptor->AddObserver( *this );
211
212   // Can only create the detector when we know the Core has been instantiated.
213   mDragAndDropDetector = DragAndDropDetector::New();
214   mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) );
215
216   if( mOrientation )
217   {
218     mOrientation->SetAdaptor(adaptor);
219   }
220
221   if( mIndicator != NULL )
222   {
223     mIndicator->SetAdaptor(mAdaptor);
224   }
225 }
226
227 RenderSurface* Window::GetSurface()
228 {
229   return mSurface;
230 }
231
232 void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode )
233 {
234   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode );
235   DALI_ASSERT_DEBUG(mOverlay);
236
237   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
238   DALI_ASSERT_DEBUG(wlSurface);
239
240   Ecore_Wl_Window* wlWindow = NULL;
241   if( wlSurface )
242   {
243     wlWindow = wlSurface->GetWlWindow();
244   }
245
246   mIndicatorVisible = visibleMode;
247
248   if ( mIndicatorVisible == Dali::Window::VISIBLE )
249   {
250     // when the indicator is visible, set proper mode for indicator server according to bg mode
251     if ( mIndicatorOpacityMode == Dali::Window::OPAQUE )
252     {
253       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
254     }
255     else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT )
256     {
257       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSLUCENT);
258     }
259     else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT )
260     {
261       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
262     }
263   }
264   else
265   {
266     // when the indicator is not visible, set TRANSPARENT mode for indicator server
267     ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSPARENT); // it means hidden indicator
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   mResizeEnabled( false ),
316   mIndicator( NULL ),
317   mIndicatorOrientation( Dali::Window::PORTRAIT ),
318   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
319   mIndicatorOpacityMode( Dali::Window::OPAQUE ),
320   mOverlay( NULL ),
321   mAdaptor( NULL ),
322   mEventHandler( NULL ),
323   mPreferredOrientation( Dali::Window::PORTRAIT ),
324   mSupportedAuxiliaryHints(),
325   mAuxiliaryHints()
326 {
327 }
328
329 Window::~Window()
330 {
331   delete mEventHandler;
332
333   if( mIndicator )
334   {
335     mIndicator->Close();
336     delete mIndicator;
337   }
338
339   if ( mAdaptor )
340   {
341     mAdaptor->RemoveObserver( *this );
342     mAdaptor->SetDragAndDropDetector( NULL );
343     mAdaptor = NULL;
344   }
345
346   delete mSurface;
347
348   mSupportedAuxiliaryHints.clear();
349   mAuxiliaryHints.clear();
350 }
351
352 void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
353 {
354   // create an Wayland window by default
355   Any surface;
356   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( positionSize, surface, name, mIsTransparent );
357
358   mSurface = windowSurface;
359
360   // create event handler for Wayland window
361   mEventHandler = new EventHandler( this );
362
363   // get auxiliary hint
364   Eina_List* hints = ecore_wl_window_aux_hints_supported_get( mEventHandler->mEcoreWindow );
365   if( hints )
366   {
367     Eina_List* l = NULL;
368     char* hint = NULL;
369
370     for( l = hints, ( hint =  static_cast< char* >( eina_list_data_get(l) ) ); l; l = eina_list_next(l), ( hint = static_cast< char* >( eina_list_data_get(l) ) ) )
371     {
372       mSupportedAuxiliaryHints.push_back( hint );
373
374       DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::Initialize: %s\n", hint );
375     }
376   }
377
378   if( !positionSize.IsEmpty() )
379   {
380     AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
381     mResizeEnabled = true;
382   }
383
384   SetClass( name, className );
385   windowSurface->Map();
386
387   mOrientation = Orientation::New(this);
388 }
389
390 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
391 {
392   if( mIndicator == NULL )
393   {
394     if( mIndicatorVisible != Dali::Window::INVISIBLE )
395     {
396       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
397       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
398       Dali::Actor actor = mIndicator->GetActor();
399       SetIndicatorActorRotation();
400       mOverlay->Add(actor);
401     }
402     // else don't create a hidden indicator
403   }
404   else // Already have indicator
405   {
406     if( mIndicatorVisible == Dali::Window::VISIBLE )
407     {
408       // If we are resuming, and rotation has changed,
409       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
410       {
411         // then close current indicator and open new one
412         mShowRotatedIndicatorOnClose = true;
413         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
414         // Don't show actor - will contain indicator for old orientation.
415       }
416     }
417   }
418
419   // set indicator visible mode
420   if( mIndicator != NULL )
421   {
422     mIndicator->SetVisible( mIndicatorVisible );
423   }
424
425   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
426   SetIndicatorProperties( show, lastOrientation );
427   mIndicatorIsShown = show;
428 }
429
430 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
431 {
432   if( mIndicatorIsShown )
433   {
434     mShowRotatedIndicatorOnClose = true;
435     mNextIndicatorOrientation = orientation;
436     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
437   }
438   else
439   {
440     // Save orientation for when the indicator is next shown
441     mShowRotatedIndicatorOnClose = false;
442     mNextIndicatorOrientation = orientation;
443   }
444 }
445
446 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
447 {
448   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
449
450   if( wlSurface )
451   {
452     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
453     if ( isShow )
454     {
455       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_ON);
456     }
457     else
458     {
459       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_OFF);
460     }
461   }
462 }
463
464 void Window::IndicatorTypeChanged(Indicator::Type type)
465 {
466 #if defined(DALI_PROFILE_MOBILE)
467   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
468
469   if( wlSurface )
470   {
471     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
472     switch(type)
473     {
474       case Indicator::INDICATOR_TYPE_1:
475         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
476         break;
477
478       case Indicator::INDICATOR_TYPE_2:
479         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
480         break;
481
482       case Indicator::INDICATOR_TYPE_UNKNOWN:
483       default:
484         break;
485     }
486   }
487 #endif //MOBILE
488 }
489
490 void Window::IndicatorClosed( IndicatorInterface* indicator )
491 {
492   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
493
494   if( mShowRotatedIndicatorOnClose )
495   {
496     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
497     mIndicator->Open(mNextIndicatorOrientation);
498     mIndicatorOrientation = mNextIndicatorOrientation;
499     SetIndicatorActorRotation();
500     DoShowIndicator(currentOrientation);
501   }
502 }
503
504 void Window::IndicatorVisibilityChanged(bool isVisible)
505 {
506   mIndicatorVisibilityChangedSignal.Emit(isVisible);
507 }
508
509 void Window::SetIndicatorActorRotation()
510 {
511   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
512   DALI_ASSERT_DEBUG( mIndicator != NULL );
513
514   Dali::Actor actor = mIndicator->GetActor();
515   switch( mIndicatorOrientation )
516   {
517     case Dali::Window::PORTRAIT:
518       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
519       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
520       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
521       break;
522     case Dali::Window::PORTRAIT_INVERSE:
523       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
524       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
525       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
526       break;
527     case Dali::Window::LANDSCAPE:
528       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
529       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
530       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
531       break;
532     case Dali::Window::LANDSCAPE_INVERSE:
533       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
534       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
535       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
536       break;
537   }
538 }
539
540 void Window::Raise()
541 {
542   ecore_wl_window_raise( mEventHandler->mEcoreWindow );
543 }
544
545 void Window::Lower()
546 {
547   ecore_wl_window_lower( mEventHandler->mEcoreWindow );
548 }
549
550 void Window::Activate()
551 {
552   ecore_wl_window_activate( mEventHandler->mEcoreWindow );
553 }
554
555 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
556 {
557   return mDragAndDropDetector;
558 }
559
560 Dali::Any Window::GetNativeHandle() const
561 {
562   if(mEventHandler)
563   {
564     return mEventHandler->mEcoreWindow;
565   }
566   else
567   {
568     return Dali::Any();
569   }
570 }
571
572 void Window::OnStart()
573 {
574   DoShowIndicator( mIndicatorOrientation );
575 }
576
577 void Window::OnPause()
578 {
579 }
580
581 void Window::OnResume()
582 {
583   // resume indicator status
584   if( mIndicator != NULL )
585   {
586     // Restore own indicator opacity
587     // Send opacity mode to indicator service when app resumed
588     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
589   }
590 }
591
592 void Window::OnStop()
593 {
594   if( mIndicator )
595   {
596     mIndicator->Close();
597   }
598
599   delete mIndicator;
600   mIndicator = NULL;
601 }
602
603 void Window::OnDestroy()
604 {
605   mAdaptor = NULL;
606 }
607
608 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
609 {
610   bool found = false;
611
612   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
613   {
614     if(mAvailableOrientations[i] == orientation)
615     {
616       found = true;
617       break;
618     }
619   }
620
621   if( ! found )
622   {
623     mAvailableOrientations.push_back(orientation);
624     SetAvailableOrientations( mAvailableOrientations );
625   }
626 }
627
628 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
629 {
630   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
631        iter != mAvailableOrientations.end(); ++iter )
632   {
633     if( *iter == orientation )
634     {
635       mAvailableOrientations.erase( iter );
636       break;
637     }
638   }
639   SetAvailableOrientations( mAvailableOrientations );
640 }
641
642 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
643 {
644   int rotations[4];
645   for( std::size_t i = 0; i < mAvailableOrientations.size(); ++i )
646   {
647     rotations[i] = static_cast< int >( mAvailableOrientations[i] );
648   }
649   ecore_wl_window_rotation_available_rotations_set( mEventHandler->mEcoreWindow, rotations, mAvailableOrientations.size() );
650 }
651
652 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
653 {
654   return mAvailableOrientations;
655 }
656
657 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
658 {
659   mPreferredOrientation = orientation;
660
661   ecore_wl_window_rotation_preferred_rotation_set( mEventHandler->mEcoreWindow, orientation );
662 }
663
664 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
665 {
666   return mPreferredOrientation;
667 }
668
669 void Window::RotationDone( int orientation, int width, int height )
670 {
671   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
672   if( wlSurface )
673   {
674     wlSurface->RequestRotation( orientation, width, height );
675   }
676
677   mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( width, height ) );
678
679   mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( width, height ) );
680 }
681
682 unsigned int Window::AddAuxiliaryHint( const std::string& hint, const std::string& value )
683 {
684   bool supported = false;
685
686   // Check if the hint is suppported
687   for( std::vector< std::string >::iterator iter = mSupportedAuxiliaryHints.begin(); iter != mSupportedAuxiliaryHints.end(); ++iter )
688   {
689     if( *iter == hint )
690     {
691       supported = true;
692       break;
693     }
694   }
695
696   if( !supported )
697   {
698     DALI_LOG_INFO( gWindowLogFilter, Debug::Concise, "Window::AddAuxiliaryHint: Not supported auxiliary hint [%s]\n", hint.c_str() );
699     return 0;
700   }
701
702   // Check if the hint is already added
703   for( unsigned int i = 0; i < mAuxiliaryHints.size(); i++ )
704   {
705     if( mAuxiliaryHints[i].first == hint )
706     {
707       // Just change the value
708       mAuxiliaryHints[i].second = value;
709
710       DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::AddAuxiliaryHint: Change! hint = %s, value = %s, id = %d\n", hint.c_str(), value.c_str(), i + 1 );
711
712       return i + 1;   // id is index + 1
713     }
714   }
715
716   // Add the hint
717   mAuxiliaryHints.push_back( std::pair< std::string, std::string >( hint, value ) );
718
719   unsigned int id = mAuxiliaryHints.size();
720
721   ecore_wl_window_aux_hint_add( mEventHandler->mEcoreWindow, static_cast< int >( id ), hint.c_str(), value.c_str() );
722
723   DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::AddAuxiliaryHint: hint = %s, value = %s, id = %d\n", hint.c_str(), value.c_str(), id );
724
725   return id;
726 }
727
728 } // Adaptor
729
730 } // Internal
731
732 } // Dali