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