React to window delete events & handle SIGTERM, SIGHUP
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / window-impl-x.cpp
1 /*
2  * Copyright (c) 2014 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 <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& posSize, const std::string& name, const std::string& className, bool isTransparent)
226 {
227   Window* window = new Window();
228   window->mIsTransparent = isTransparent;
229   window->Initialize(posSize, 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   mIndicator(NULL),
347   mIndicatorOrientation(Dali::Window::PORTRAIT),
348   mNextIndicatorOrientation(Dali::Window::PORTRAIT),
349   mIndicatorOpacityMode(Dali::Window::OPAQUE),
350   mOverlay(NULL),
351   mAdaptor(NULL),
352   mEventHandler(NULL),
353   mPreferredOrientation(Dali::Window::PORTRAIT)
354 {
355
356   // Detect if we're not running in a ecore main loop (e.g. libuv).
357   // Typically ecore_x_init is called by app_efl_main->elm_init
358   // but if we're not using app_efl_main then we have to call it ourselves
359   // This is a hack until we create a pure X Window class
360   if( ecore_x_display_get() == NULL )
361   {
362     mEcoreEventHander = false;
363     ecore_x_init (NULL); //  internally calls _ecore_x_input_init
364   }
365
366 }
367
368 Window::~Window()
369 {
370   delete mEventHandler;
371
372   if( mIndicator )
373   {
374     mOverlay->Remove( mIndicator->GetActor() );
375     Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
376     Dali::RenderTask indicatorTask = taskList.GetTask(0);
377     mOverlay->GetOverlayRenderTasks().RemoveTask(indicatorTask);
378     mIndicator->Close();
379     delete mIndicator;
380   }
381
382   if( mAdaptor )
383   {
384     mAdaptor->RemoveObserver( *this );
385     mAdaptor->SetDragAndDropDetector( NULL );
386     mAdaptor = NULL;
387   }
388
389   delete mSurface;
390 }
391
392 void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
393 {
394   // create an X11 window by default
395   Any surface;
396   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, className, mIsTransparent );
397   windowSurface->Map();
398
399   mSurface = windowSurface;
400
401   mOrientation = Orientation::New(this);
402
403   // create event handler for X11 window
404   mEventHandler = new EventHandler( this );
405 }
406
407 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
408 {
409   if( mIndicator == NULL )
410   {
411     if( mIndicatorVisible != Dali::Window::INVISIBLE )
412     {
413       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
414       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
415       Dali::Actor actor = mIndicator->GetActor();
416       SetIndicatorActorRotation();
417       mOverlay->Add(actor);
418     }
419     // else don't create a hidden indicator
420   }
421   else // Already have indicator
422   {
423     if( mIndicatorVisible == Dali::Window::VISIBLE )
424     {
425       // If we are resuming, and rotation has changed,
426       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
427       {
428         // then close current indicator and open new one
429         mShowRotatedIndicatorOnClose = true;
430         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
431         // Don't show actor - will contain indicator for old orientation.
432       }
433     }
434   }
435
436   // set indicator visible mode
437   if( mIndicator != NULL )
438   {
439     mIndicator->SetVisible( mIndicatorVisible );
440   }
441
442   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
443   SetIndicatorProperties( show, lastOrientation );
444   mIndicatorIsShown = show;
445 }
446
447 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
448 {
449   if( mIndicatorIsShown )
450   {
451     mShowRotatedIndicatorOnClose = true;
452     mNextIndicatorOrientation = orientation;
453     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
454   }
455   else
456   {
457     // Save orientation for when the indicator is next shown
458     mShowRotatedIndicatorOnClose = false;
459     mNextIndicatorOrientation = orientation;
460   }
461 }
462
463 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
464 {
465   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
466   if( x11Window )
467   {
468     Ecore_X_Window win = x11Window->GetXWindow();
469
470     int show_state = static_cast<int>( isShow );
471     ecore_x_window_prop_property_set( win,
472                                       ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE,
473                                       ECORE_X_ATOM_CARDINAL, 32, &show_state, 1);
474
475     if ( isShow )
476     {
477       ecore_x_e_illume_indicator_state_set(win, ECORE_X_ILLUME_INDICATOR_STATE_ON);
478     }
479     else
480     {
481       ecore_x_e_illume_indicator_state_set(win, ECORE_X_ILLUME_INDICATOR_STATE_OFF);
482     }
483   }
484 }
485
486 void Window::IndicatorTypeChanged(Indicator::Type type)
487 {
488   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
489   if( x11Window )
490   {
491 #ifndef DALI_PROFILE_UBUNTU
492     Ecore_X_Window win = x11Window->GetXWindow();
493     switch(type)
494     {
495       case Indicator::INDICATOR_TYPE_1:
496         ecore_x_e_illume_indicator_type_set( win, ECORE_X_ILLUME_INDICATOR_TYPE_1 );
497         break;
498
499       case Indicator::INDICATOR_TYPE_2:
500         ecore_x_e_illume_indicator_type_set( win, ECORE_X_ILLUME_INDICATOR_TYPE_2 );
501         break;
502
503       case Indicator::INDICATOR_TYPE_UNKNOWN:
504       default:
505         break;
506     }
507 #endif // DALI_PROFILE_UBUNTU
508   }
509 }
510
511 void Window::IndicatorClosed( Indicator* indicator )
512 {
513   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
514
515   if( mShowRotatedIndicatorOnClose )
516   {
517     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
518     mIndicator->Open(mNextIndicatorOrientation);
519     mIndicatorOrientation = mNextIndicatorOrientation;
520     SetIndicatorActorRotation();
521     DoShowIndicator(currentOrientation);
522   }
523 }
524
525 void Window::IndicatorVisibilityChanged(bool isVisible)
526 {
527   mIndicatorVisibilityChangedSignal.Emit(isVisible);
528 }
529
530 void Window::SetIndicatorActorRotation()
531 {
532   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
533   DALI_ASSERT_DEBUG( mIndicator != NULL );
534
535   Dali::Actor actor = mIndicator->GetActor();
536   switch( mIndicatorOrientation )
537   {
538     case Dali::Window::PORTRAIT:
539       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
540       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
541       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
542       break;
543     case Dali::Window::PORTRAIT_INVERSE:
544       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
545       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
546       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
547       break;
548     case Dali::Window::LANDSCAPE:
549       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
550       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
551       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
552       break;
553     case Dali::Window::LANDSCAPE_INVERSE:
554       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
555       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
556       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
557       break;
558   }
559 }
560
561 void Window::Raise()
562 {
563   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
564   if( x11Window )
565   {
566     Ecore_X_Window win = x11Window->GetXWindow();
567     ecore_x_window_raise(win);
568   }
569 }
570
571 void Window::Lower()
572 {
573   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
574   if( x11Window )
575   {
576     Ecore_X_Window win = x11Window->GetXWindow();
577     ecore_x_window_lower(win);
578   }
579 }
580
581 void Window::Activate()
582 {
583   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
584   if( x11Window )
585   {
586     Ecore_X_Window win = x11Window->GetXWindow();
587     ecore_x_netwm_client_active_request(ecore_x_window_root_get(win), win, 1 /* request type, 1:application, 2:pager */, 0);
588   }
589 }
590
591 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
592 {
593   return mDragAndDropDetector;
594 }
595
596 Dali::Any Window::GetNativeHandle() const
597 {
598   if(mEventHandler)
599   {
600     return mEventHandler->mEcoreWindow;
601   }
602   else
603   {
604     return Dali::Any();
605   }
606 }
607
608 void Window::OnStart()
609 {
610   ShowIndicator( mIndicatorVisible );
611 }
612
613 void Window::OnPause()
614 {
615 }
616
617 void Window::OnResume()
618 {
619   // resume indicator status
620   if( mIndicator != NULL )
621   {
622     // Restore own indicator opacity
623     // Send opacity mode to indicator service when app resumed
624     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
625   }
626 }
627
628 void Window::OnStop()
629 {
630   if( mIndicator )
631   {
632     mIndicator->Close();
633   }
634
635   delete mIndicator;
636   mIndicator = NULL;
637 }
638
639 void Window::OnDestroy()
640 {
641   mAdaptor = NULL;
642 }
643
644 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
645 {
646   bool found = false;
647
648   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
649   {
650     if(mAvailableOrientations[i] == orientation)
651     {
652       found = true;
653       break;
654     }
655   }
656
657   if( ! found )
658   {
659     mAvailableOrientations.push_back(orientation);
660     SetAvailableOrientations( mAvailableOrientations );
661   }
662 }
663
664 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
665 {
666   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
667        iter != mAvailableOrientations.end(); ++iter )
668   {
669     if( *iter == orientation )
670     {
671       mAvailableOrientations.erase( iter );
672       break;
673     }
674   }
675   SetAvailableOrientations( mAvailableOrientations );
676 }
677
678 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
679 {
680   DALI_ASSERT_ALWAYS( mAvailableOrientations.size() <= 4 && "Incorrect number of available orientations" );
681
682   mAvailableOrientations = orientations;
683   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
684   if( x11Window )
685   {
686 #ifndef DALI_PROFILE_UBUNTU
687     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
688     if( ! mWMRotationAppSet )
689     {
690       mWMRotationAppSet = true;
691       ecore_x_e_window_rotation_app_set(ecoreWindow, EINA_TRUE);
692     }
693
694     int rotations[4];
695     for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
696     {
697       rotations[i] = static_cast<int>(mAvailableOrientations[i]);
698     }
699     ecore_x_e_window_rotation_available_rotations_set(ecoreWindow, rotations, mAvailableOrientations.size() );
700 #endif // DALI_PROFILE_UBUNTU
701   }
702 }
703
704 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
705 {
706   return mAvailableOrientations;
707 }
708
709 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
710 {
711   mPreferredOrientation = orientation;
712
713   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
714   if( x11Window )
715   {
716 #ifndef DALI_PROFILE_UBUNTU
717     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
718
719     if( ! mWMRotationAppSet )
720     {
721       mWMRotationAppSet = true;
722       ecore_x_e_window_rotation_app_set(ecoreWindow, EINA_TRUE);
723     }
724
725     ecore_x_e_window_rotation_preferred_rotation_set(ecoreWindow, orientation);
726 #endif // DALI_PROFILE_UBUNTU
727   }
728 }
729
730 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
731 {
732   return mPreferredOrientation;
733 }
734
735 void Window::RotationDone( int orientation, int width, int height )
736 {
737   // Tell window manager we're done
738   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
739   if( x11Window )
740   {
741 #ifndef DALI_PROFILE_UBUNTU
742     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
743     Ecore_X_Window root = ecore_x_window_root_get(ecoreWindow);
744
745     /**
746      * send rotation done message to wm, even if window is already rotated.
747      * that's why wm must be wait for comming rotation done message
748      * after sending rotation request.
749      */
750     ecore_x_e_window_rotation_change_done_send(root, ecoreWindow, orientation, width, height);
751
752     /**
753      * set rotate window property
754      */
755     int angles[2] = { orientation, orientation };
756     ecore_x_window_prop_property_set( ecoreWindow,
757                                      ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
758                                      ECORE_X_ATOM_CARDINAL, 32, &angles, 2 );
759 #endif // DALI_PROFILE_UBUNTU
760   }
761 }
762
763
764 } // Adaptor
765 } // Internal
766 } // Dali