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