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