[3.0] Support screen rotation
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / window-impl-x.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_X.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
30 // INTERNAL HEADERS
31 #include <window-render-surface.h>
32 #include <drag-and-drop-detector-impl.h>
33 #include <ecore-indicator-impl.h>
34 #include <window-visibility-observer.h>
35 #include <orientation.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     mClientMessagehandler( NULL ),
68     mWindowDeleteRequestHandler( NULL ),
69     mEcoreWindow( 0 )
70   {
71     // store ecore window handle
72     ECore::WindowRenderSurface* x11Window( dynamic_cast< ECore::WindowRenderSurface * >( mWindow->mSurface ) );
73     if( x11Window )
74     {
75       mEcoreWindow = x11Window->GetXWindow();
76     }
77     DALI_ASSERT_ALWAYS( mEcoreWindow != 0 && "There is no ecore x window");
78
79 #ifndef DALI_PROFILE_UBUNTU
80     // set property on window to get deiconify approve client message
81     unsigned int tmp = 1;
82     ecore_x_window_prop_card32_set(mEcoreWindow,
83                              ECORE_X_ATOM_E_DEICONIFY_APPROVE,
84                              &tmp, 1);
85 #endif // DALI_PROFILE_UBUNTU
86
87     if( mWindow->mEcoreEventHander )
88     {
89       ecore_x_input_multi_select( mEcoreWindow );
90
91       // This ensures that we catch the window close (or delete) request
92       ecore_x_icccm_protocol_set( mEcoreWindow, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, EINA_TRUE );
93
94       mWindowPropertyHandler=  ecore_event_handler_add( ECORE_X_EVENT_WINDOW_PROPERTY,  EcoreEventWindowPropertyChanged, this );
95       mClientMessagehandler =  ecore_event_handler_add( ECORE_X_EVENT_CLIENT_MESSAGE,  EcoreEventClientMessage, this );
96       mWindowDeleteRequestHandler = ecore_event_handler_add( ECORE_X_EVENT_WINDOW_DELETE_REQUEST, EcoreEventWindowDeleteRequest, this );
97     }
98   }
99
100   /**
101    * Destructor
102    */
103   ~EventHandler()
104   {
105     if ( mWindowPropertyHandler )
106     {
107       ecore_event_handler_del( mWindowPropertyHandler );
108     }
109     if ( mClientMessagehandler )
110     {
111       ecore_event_handler_del( mClientMessagehandler );
112     }
113     if ( mWindowDeleteRequestHandler )
114     {
115       ecore_event_handler_del( mWindowDeleteRequestHandler );
116     }
117   }
118
119   // Static methods
120
121   /// Called when the window properties are changed.
122   static Eina_Bool EcoreEventWindowPropertyChanged( void* data, int type, void* event )
123   {
124     Ecore_X_Event_Window_Property* propertyChangedEvent( (Ecore_X_Event_Window_Property*)event );
125     EventHandler* handler( (EventHandler*)data );
126     Eina_Bool handled( ECORE_CALLBACK_PASS_ON );
127
128     if ( handler && handler->mWindow )
129     {
130       WindowVisibilityObserver* observer( handler->mWindow->mAdaptor );
131       if ( observer && ( propertyChangedEvent->win == handler->mEcoreWindow ) )
132       {
133         Ecore_X_Window_State_Hint state( ecore_x_icccm_state_get( propertyChangedEvent->win ) );
134
135         switch ( state )
136         {
137           case ECORE_X_WINDOW_STATE_HINT_WITHDRAWN:
138           {
139             // Window was hidden.
140             observer->OnWindowHidden();
141             DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Withdrawn\n", handler->mEcoreWindow );
142             handled = ECORE_CALLBACK_DONE;
143           }
144           break;
145
146           case ECORE_X_WINDOW_STATE_HINT_ICONIC:
147           {
148             // Window was iconified (minimised).
149             observer->OnWindowHidden();
150             DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Iconfied\n", handler->mEcoreWindow );
151             handled = ECORE_CALLBACK_DONE;
152           }
153           break;
154
155           case ECORE_X_WINDOW_STATE_HINT_NORMAL:
156           {
157             // Window was shown.
158             observer->OnWindowShown();
159             DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Shown\n", handler->mEcoreWindow );
160             handled = ECORE_CALLBACK_DONE;
161           }
162           break;
163
164           default:
165             // Ignore
166             break;
167         }
168       }
169     }
170
171     return handled;
172   }
173
174   /// Called when the window properties are changed.
175   static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
176   {
177     Eina_Bool handled( ECORE_CALLBACK_PASS_ON );
178 #ifndef DALI_PROFILE_UBUNTU
179     Ecore_X_Event_Client_Message* clientMessageEvent( (Ecore_X_Event_Client_Message*)event );
180     EventHandler* handler( (EventHandler*)data );
181
182     if (clientMessageEvent->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
183     {
184       ECore::WindowRenderSurface* x11Window( dynamic_cast< ECore::WindowRenderSurface * >( handler->mWindow->mSurface ) );
185       WindowVisibilityObserver* observer( handler->mWindow->mAdaptor );
186
187       if ( observer && ( (unsigned int)clientMessageEvent->data.l[0] == handler->mEcoreWindow ) )
188       {
189         if (clientMessageEvent->data.l[1] == 0) //wm sends request message using value 0
190         {
191           observer->OnWindowShown();
192
193           // request to approve the deiconify. render-surface should send proper event after real rendering
194           if(x11Window)
195           {
196             x11Window->RequestToApproveDeiconify();
197           }
198
199           handled = ECORE_CALLBACK_DONE;
200         }
201       }
202     }
203 #endif // DALI_PROFILE_UBUNTU
204
205     return handled;
206   }
207
208   /// Called when the window receives a delete request
209   static Eina_Bool EcoreEventWindowDeleteRequest( void* data, int type, void* event )
210   {
211     EventHandler* handler( (EventHandler*)data );
212     handler->mWindow->mDeleteRequestSignal.Emit();
213     return ECORE_CALLBACK_DONE;
214   }
215
216   // Data
217   Window* mWindow;
218   Ecore_Event_Handler* mWindowPropertyHandler;
219   Ecore_Event_Handler* mClientMessagehandler;
220   Ecore_Event_Handler* mWindowDeleteRequestHandler;
221   Ecore_X_Window mEcoreWindow;
222 };
223
224
225 Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
226 {
227   Window* window = new Window();
228   window->mIsTransparent = isTransparent;
229   window->Initialize( positionSize, name, className );
230   return window;
231 }
232
233 void Window::SetAdaptor(Dali::Adaptor& adaptor)
234 {
235   DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" );
236   mStarted = true;
237
238   // Only create one overlay per window
239   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
240   Integration::Core& core = adaptorImpl.GetCore();
241   mOverlay = &core.GetSystemOverlay();
242
243   Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
244   taskList.CreateTask();
245
246   mAdaptor = &adaptorImpl;
247   mAdaptor->AddObserver( *this );
248
249   // Can only create the detector when we know the Core has been instantiated.
250   mDragAndDropDetector = DragAndDropDetector::New();
251   mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) );
252
253   if( mOrientation )
254   {
255     mOrientation->SetAdaptor(adaptor);
256   }
257
258   if( mIndicator != NULL )
259   {
260     mIndicator->SetAdaptor(mAdaptor);
261   }
262 }
263
264 RenderSurface* Window::GetSurface()
265 {
266   return mSurface;
267 }
268
269 void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode )
270 {
271   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode );
272   DALI_ASSERT_DEBUG(mOverlay);
273
274   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
275   DALI_ASSERT_DEBUG(x11Window);
276   Ecore_X_Window xWinId = x11Window->GetXWindow();
277
278   mIndicatorVisible = visibleMode;
279
280   if ( mIndicatorVisible == Dali::Window::VISIBLE )
281   {
282     // when the indicator is visible, set proper mode for indicator server according to bg mode
283     if ( mIndicatorOpacityMode == Dali::Window::OPAQUE )
284     {
285       ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_OPAQUE);
286     }
287     else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT )
288     {
289       ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_TRANSLUCENT);
290     }
291 #if defined(DALI_PROFILE_MOBILE)
292     else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT )
293     {
294       ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_OPAQUE);
295     }
296 #endif
297   }
298   else
299   {
300     // when the indicator is not visible, set TRANSPARENT mode for indicator server
301     ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_TRANSPARENT); // it means hidden indicator
302   }
303
304   DoShowIndicator( mIndicatorOrientation );
305 }
306
307 void Window::RotateIndicator(Dali::Window::WindowOrientation orientation)
308 {
309   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation );
310
311   DoRotateIndicator( orientation );
312 }
313
314 void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode )
315 {
316   mIndicatorOpacityMode = opacityMode;
317
318   if( mIndicator != NULL )
319   {
320     mIndicator->SetOpacityMode( opacityMode );
321   }
322 }
323
324 void Window::SetClass(std::string name, std::string klass)
325 {
326   // Get render surface's x11 window
327   if( mSurface )
328   {
329     ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
330     if( x11Window )
331     {
332       ecore_x_icccm_name_class_set( x11Window->GetXWindow(), name.c_str(), klass.c_str() );
333     }
334   }
335 }
336
337 Window::Window()
338 : mSurface( NULL ),
339   mIndicatorVisible( Dali::Window::INVISIBLE ),
340   mIndicatorIsShown( false ),
341   mShowRotatedIndicatorOnClose( false ),
342   mStarted( false ),
343   mIsTransparent( false ),
344   mWMRotationAppSet( false ),
345   mEcoreEventHander( true ),
346   mResizeEnabled( true ),
347   mIndicator( NULL ),
348   mIndicatorOrientation( Dali::Window::PORTRAIT ),
349   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
350   mIndicatorOpacityMode( Dali::Window::OPAQUE ),
351   mOverlay( NULL ),
352   mAdaptor( NULL ),
353   mEventHandler( NULL ),
354   mPreferredOrientation( Dali::Window::PORTRAIT ),
355   mSupportedAuxiliaryHints(),
356   mAuxiliaryHints()
357 {
358
359   // Detect if we're not running in a ecore main loop (e.g. libuv).
360   // Typically ecore_x_init is called by app_efl_main->elm_init
361   // but if we're not using app_efl_main then we have to call it ourselves
362   // This is a hack until we create a pure X Window class
363   if( ecore_x_display_get() == NULL )
364   {
365     mEcoreEventHander = false;
366     ecore_x_init (NULL); //  internally calls _ecore_x_input_init
367   }
368
369 }
370
371 Window::~Window()
372 {
373   delete mEventHandler;
374
375   if( mIndicator )
376   {
377     mOverlay->Remove( mIndicator->GetActor() );
378     Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
379     Dali::RenderTask indicatorTask = taskList.GetTask(0);
380     mOverlay->GetOverlayRenderTasks().RemoveTask(indicatorTask);
381     mIndicator->Close();
382     delete mIndicator;
383   }
384
385   if( mAdaptor )
386   {
387     mAdaptor->RemoveObserver( *this );
388     mAdaptor->SetDragAndDropDetector( NULL );
389     mAdaptor = NULL;
390   }
391
392   delete mSurface;
393 }
394
395 void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
396 {
397   // create an X11 window by default
398   Any surface;
399   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( positionSize, surface, name, className, mIsTransparent );
400   windowSurface->Map();
401
402   mSurface = windowSurface;
403
404   mOrientation = Orientation::New(this);
405
406   // create event handler for X11 window
407   mEventHandler = new EventHandler( this );
408 }
409
410 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
411 {
412   if( mIndicator == NULL )
413   {
414     if( mIndicatorVisible != Dali::Window::INVISIBLE )
415     {
416       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
417       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
418       Dali::Actor actor = mIndicator->GetActor();
419       SetIndicatorActorRotation();
420       mOverlay->Add(actor);
421     }
422     // else don't create a hidden indicator
423   }
424   else // Already have indicator
425   {
426     if( mIndicatorVisible == Dali::Window::VISIBLE )
427     {
428       // If we are resuming, and rotation has changed,
429       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
430       {
431         // then close current indicator and open new one
432         mShowRotatedIndicatorOnClose = true;
433         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
434         // Don't show actor - will contain indicator for old orientation.
435       }
436     }
437   }
438
439   // set indicator visible mode
440   if( mIndicator != NULL )
441   {
442     mIndicator->SetVisible( mIndicatorVisible );
443   }
444
445   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
446   SetIndicatorProperties( show, lastOrientation );
447   mIndicatorIsShown = show;
448 }
449
450 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
451 {
452   if( mIndicatorIsShown )
453   {
454     mShowRotatedIndicatorOnClose = true;
455     mNextIndicatorOrientation = orientation;
456     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
457   }
458   else
459   {
460     // Save orientation for when the indicator is next shown
461     mShowRotatedIndicatorOnClose = false;
462     mNextIndicatorOrientation = orientation;
463   }
464 }
465
466 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
467 {
468   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
469   if( x11Window )
470   {
471     Ecore_X_Window win = x11Window->GetXWindow();
472
473     int show_state = static_cast<int>( isShow );
474     ecore_x_window_prop_property_set( win,
475                                       ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE,
476                                       ECORE_X_ATOM_CARDINAL, 32, &show_state, 1);
477
478     if ( isShow )
479     {
480       ecore_x_e_illume_indicator_state_set(win, ECORE_X_ILLUME_INDICATOR_STATE_ON);
481     }
482     else
483     {
484       ecore_x_e_illume_indicator_state_set(win, ECORE_X_ILLUME_INDICATOR_STATE_OFF);
485     }
486   }
487 }
488
489 void Window::IndicatorTypeChanged(Indicator::Type type)
490 {
491   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
492   if( x11Window )
493   {
494 #ifndef DALI_PROFILE_UBUNTU
495     Ecore_X_Window win = x11Window->GetXWindow();
496     switch(type)
497     {
498       case Indicator::INDICATOR_TYPE_1:
499         ecore_x_e_illume_indicator_type_set( win, ECORE_X_ILLUME_INDICATOR_TYPE_1 );
500         break;
501
502       case Indicator::INDICATOR_TYPE_2:
503         ecore_x_e_illume_indicator_type_set( win, ECORE_X_ILLUME_INDICATOR_TYPE_2 );
504         break;
505
506       case Indicator::INDICATOR_TYPE_UNKNOWN:
507       default:
508         break;
509     }
510 #endif // DALI_PROFILE_UBUNTU
511   }
512 }
513
514 void Window::IndicatorClosed( IndicatorInterface* indicator )
515 {
516   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
517
518   if( mShowRotatedIndicatorOnClose )
519   {
520     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
521     mIndicator->Open(mNextIndicatorOrientation);
522     mIndicatorOrientation = mNextIndicatorOrientation;
523     SetIndicatorActorRotation();
524     DoShowIndicator(currentOrientation);
525   }
526 }
527
528 void Window::IndicatorVisibilityChanged(bool isVisible)
529 {
530   mIndicatorVisibilityChangedSignal.Emit(isVisible);
531 }
532
533 void Window::SetIndicatorActorRotation()
534 {
535   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
536   DALI_ASSERT_DEBUG( mIndicator != NULL );
537
538   Dali::Actor actor = mIndicator->GetActor();
539   switch( mIndicatorOrientation )
540   {
541     case Dali::Window::PORTRAIT:
542       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
543       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
544       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
545       break;
546     case Dali::Window::PORTRAIT_INVERSE:
547       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
548       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
549       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
550       break;
551     case Dali::Window::LANDSCAPE:
552       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
553       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
554       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
555       break;
556     case Dali::Window::LANDSCAPE_INVERSE:
557       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
558       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
559       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
560       break;
561   }
562 }
563
564 void Window::Raise()
565 {
566   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
567   if( x11Window )
568   {
569     Ecore_X_Window win = x11Window->GetXWindow();
570     ecore_x_window_raise(win);
571   }
572 }
573
574 void Window::Lower()
575 {
576   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
577   if( x11Window )
578   {
579     Ecore_X_Window win = x11Window->GetXWindow();
580     ecore_x_window_lower(win);
581   }
582 }
583
584 void Window::Activate()
585 {
586   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
587   if( x11Window )
588   {
589     Ecore_X_Window win = x11Window->GetXWindow();
590     ecore_x_netwm_client_active_request(ecore_x_window_root_get(win), win, 1 /* request type, 1:application, 2:pager */, 0);
591   }
592 }
593
594 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
595 {
596   return mDragAndDropDetector;
597 }
598
599 Dali::Any Window::GetNativeHandle() const
600 {
601   if(mEventHandler)
602   {
603     return mEventHandler->mEcoreWindow;
604   }
605   else
606   {
607     return Dali::Any();
608   }
609 }
610
611 void Window::OnStart()
612 {
613   ShowIndicator( mIndicatorVisible );
614 }
615
616 void Window::OnPause()
617 {
618 }
619
620 void Window::OnResume()
621 {
622   // resume indicator status
623   if( mIndicator != NULL )
624   {
625     // Restore own indicator opacity
626     // Send opacity mode to indicator service when app resumed
627     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
628   }
629 }
630
631 void Window::OnStop()
632 {
633   if( mIndicator )
634   {
635     mIndicator->Close();
636   }
637
638   delete mIndicator;
639   mIndicator = NULL;
640 }
641
642 void Window::OnDestroy()
643 {
644   mAdaptor = NULL;
645 }
646
647 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
648 {
649   bool found = false;
650
651   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
652   {
653     if(mAvailableOrientations[i] == orientation)
654     {
655       found = true;
656       break;
657     }
658   }
659
660   if( ! found )
661   {
662     mAvailableOrientations.push_back(orientation);
663     SetAvailableOrientations( mAvailableOrientations );
664   }
665 }
666
667 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
668 {
669   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
670        iter != mAvailableOrientations.end(); ++iter )
671   {
672     if( *iter == orientation )
673     {
674       mAvailableOrientations.erase( iter );
675       break;
676     }
677   }
678   SetAvailableOrientations( mAvailableOrientations );
679 }
680
681 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
682 {
683   DALI_ASSERT_ALWAYS( mAvailableOrientations.size() <= 4 && "Incorrect number of available orientations" );
684
685   mAvailableOrientations = orientations;
686   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
687   if( x11Window )
688   {
689 #ifndef DALI_PROFILE_UBUNTU
690     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
691     if( ! mWMRotationAppSet )
692     {
693       mWMRotationAppSet = true;
694       ecore_x_e_window_rotation_app_set(ecoreWindow, EINA_TRUE);
695     }
696
697     int rotations[4];
698     for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
699     {
700       rotations[i] = static_cast<int>(mAvailableOrientations[i]);
701     }
702     ecore_x_e_window_rotation_available_rotations_set(ecoreWindow, rotations, mAvailableOrientations.size() );
703 #endif // DALI_PROFILE_UBUNTU
704   }
705 }
706
707 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
708 {
709   return mAvailableOrientations;
710 }
711
712 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
713 {
714   mPreferredOrientation = orientation;
715
716   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
717   if( x11Window )
718   {
719 #ifndef DALI_PROFILE_UBUNTU
720     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
721
722     if( ! mWMRotationAppSet )
723     {
724       mWMRotationAppSet = true;
725       ecore_x_e_window_rotation_app_set(ecoreWindow, EINA_TRUE);
726     }
727
728     ecore_x_e_window_rotation_preferred_rotation_set(ecoreWindow, orientation);
729 #endif // DALI_PROFILE_UBUNTU
730   }
731 }
732
733 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
734 {
735   return mPreferredOrientation;
736 }
737
738 void Window::RotationDone( int orientation, int width, int height )
739 {
740   // Tell window manager we're done
741   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
742   if( x11Window )
743   {
744 #ifndef DALI_PROFILE_UBUNTU
745     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
746     Ecore_X_Window root = ecore_x_window_root_get(ecoreWindow);
747
748     /**
749      * send rotation done message to wm, even if window is already rotated.
750      * that's why wm must be wait for comming rotation done message
751      * after sending rotation request.
752      */
753     ecore_x_e_window_rotation_change_done_send(root, ecoreWindow, orientation, width, height);
754
755     /**
756      * set rotate window property
757      */
758     int angles[2] = { orientation, orientation };
759     ecore_x_window_prop_property_set( ecoreWindow,
760                                      ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
761                                      ECORE_X_ATOM_CARDINAL, 32, &angles, 2 );
762
763     mAdaptor->SurfaceResizePrepare( Adaptor::SurfaceSize( width, height ) );
764
765     mAdaptor->SurfaceResizeComplete( Adaptor::SurfaceSize( width, height ) );
766 #endif // DALI_PROFILE_UBUNTU
767   }
768 }
769
770 unsigned int Window::AddAuxiliaryHint( const std::string& hint, const std::string& value )
771 {
772   return -1;
773 }
774
775 } // Adaptor
776 } // Internal
777 } // Dali