Support window resizing
[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 // Ecore is littered with C style cast
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wold-style-cast"
25 #include <Ecore.h>
26 #include <Ecore_X.h>
27
28 #include <dali/integration-api/core.h>
29 #include <dali/integration-api/system-overlay.h>
30 #include <dali/public-api/render-tasks/render-task.h>
31 #include <dali/public-api/render-tasks/render-task-list.h>
32
33 // INTERNAL HEADERS
34 #include <window-render-surface.h>
35 #include <drag-and-drop-detector-impl.h>
36 #include <ecore-indicator-impl.h>
37 #include <window-visibility-observer.h>
38 #include <orientation.h>
39 #include <orientation-impl.h>
40
41 namespace
42 {
43 const float INDICATOR_ANIMATION_DURATION( 0.18f ); // 180 milli seconds
44 const float INDICATOR_SHOW_Y_POSITION( 0.0f );
45 const float INDICATOR_HIDE_Y_POSITION( -52.0f );
46 }
47
48 namespace Dali
49 {
50 namespace Internal
51 {
52 namespace Adaptor
53 {
54 #if defined(DEBUG_ENABLED)
55 Debug::Filter* gWindowLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_WINDOW");
56 #endif
57
58 /**
59  * TODO: Abstract Window class out and move this into a window implementation for Ecore
60  */
61 struct Window::EventHandler
62 {
63   /**
64    * Constructor
65    * @param[in]  window  A pointer to the window class.
66    */
67   EventHandler( Window* window )
68   : mWindow( window ),
69     mWindowPropertyHandler( NULL ),
70     mClientMessagehandler( NULL ),
71     mWindowDeleteRequestHandler( NULL ),
72     mEcoreWindow( 0 )
73   {
74     // store ecore window handle
75     ECore::WindowRenderSurface* x11Window( dynamic_cast< ECore::WindowRenderSurface * >( mWindow->mSurface ) );
76     if( x11Window )
77     {
78       mEcoreWindow = x11Window->GetXWindow();
79     }
80     DALI_ASSERT_ALWAYS( mEcoreWindow != 0 && "There is no ecore x window");
81
82 #ifndef DALI_PROFILE_UBUNTU
83     // set property on window to get deiconify approve client message
84     unsigned int tmp = 1;
85     ecore_x_window_prop_card32_set(mEcoreWindow,
86                              ECORE_X_ATOM_E_DEICONIFY_APPROVE,
87                              &tmp, 1);
88 #endif // DALI_PROFILE_UBUNTU
89
90     if( mWindow->mEcoreEventHander )
91     {
92       ecore_x_input_multi_select( mEcoreWindow );
93
94       // This ensures that we catch the window close (or delete) request
95       ecore_x_icccm_protocol_set( mEcoreWindow, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, EINA_TRUE );
96
97       mWindowPropertyHandler=  ecore_event_handler_add( ECORE_X_EVENT_WINDOW_PROPERTY,  EcoreEventWindowPropertyChanged, this );
98       mClientMessagehandler =  ecore_event_handler_add( ECORE_X_EVENT_CLIENT_MESSAGE,  EcoreEventClientMessage, this );
99       mWindowDeleteRequestHandler = ecore_event_handler_add( ECORE_X_EVENT_WINDOW_DELETE_REQUEST, EcoreEventWindowDeleteRequest, this );
100     }
101   }
102
103   /**
104    * Destructor
105    */
106   ~EventHandler()
107   {
108     if ( mWindowPropertyHandler )
109     {
110       ecore_event_handler_del( mWindowPropertyHandler );
111     }
112     if ( mClientMessagehandler )
113     {
114       ecore_event_handler_del( mClientMessagehandler );
115     }
116     if ( mWindowDeleteRequestHandler )
117     {
118       ecore_event_handler_del( mWindowDeleteRequestHandler );
119     }
120   }
121
122   // Static methods
123
124   /// Called when the window properties are changed.
125   static Eina_Bool EcoreEventWindowPropertyChanged( void* data, int type, void* event )
126   {
127     Ecore_X_Event_Window_Property* propertyChangedEvent( (Ecore_X_Event_Window_Property*)event );
128     EventHandler* handler( (EventHandler*)data );
129     Eina_Bool handled( ECORE_CALLBACK_PASS_ON );
130
131     if ( handler && handler->mWindow )
132     {
133       WindowVisibilityObserver* observer( handler->mWindow->mAdaptor );
134       if ( observer && ( propertyChangedEvent->win == handler->mEcoreWindow ) )
135       {
136         Ecore_X_Window_State_Hint state( ecore_x_icccm_state_get( propertyChangedEvent->win ) );
137
138         switch ( state )
139         {
140           case ECORE_X_WINDOW_STATE_HINT_WITHDRAWN:
141           {
142             // Window was hidden.
143             observer->OnWindowHidden();
144             DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Withdrawn\n", handler->mEcoreWindow );
145             handled = ECORE_CALLBACK_DONE;
146           }
147           break;
148
149           case ECORE_X_WINDOW_STATE_HINT_ICONIC:
150           {
151             // Window was iconified (minimised).
152             observer->OnWindowHidden();
153             DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Iconfied\n", handler->mEcoreWindow );
154             handled = ECORE_CALLBACK_DONE;
155           }
156           break;
157
158           case ECORE_X_WINDOW_STATE_HINT_NORMAL:
159           {
160             // Window was shown.
161             observer->OnWindowShown();
162             DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window (%d) Shown\n", handler->mEcoreWindow );
163             handled = ECORE_CALLBACK_DONE;
164           }
165           break;
166
167           default:
168             // Ignore
169             break;
170         }
171       }
172     }
173
174     return handled;
175   }
176
177   /// Called when the window properties are changed.
178   static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
179   {
180     Eina_Bool handled( ECORE_CALLBACK_PASS_ON );
181 #ifndef DALI_PROFILE_UBUNTU
182     Ecore_X_Event_Client_Message* clientMessageEvent( (Ecore_X_Event_Client_Message*)event );
183     EventHandler* handler( (EventHandler*)data );
184
185     if (clientMessageEvent->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
186     {
187       ECore::WindowRenderSurface* x11Window( dynamic_cast< ECore::WindowRenderSurface * >( handler->mWindow->mSurface ) );
188       WindowVisibilityObserver* observer( handler->mWindow->mAdaptor );
189
190       if ( observer && ( (unsigned int)clientMessageEvent->data.l[0] == handler->mEcoreWindow ) )
191       {
192         if (clientMessageEvent->data.l[1] == 0) //wm sends request message using value 0
193         {
194           observer->OnWindowShown();
195
196           // request to approve the deiconify. render-surface should send proper event after real rendering
197           if(x11Window)
198           {
199             x11Window->RequestToApproveDeiconify();
200           }
201
202           handled = ECORE_CALLBACK_DONE;
203         }
204       }
205     }
206 #endif // DALI_PROFILE_UBUNTU
207
208     return handled;
209   }
210
211   /// Called when the window receives a delete request
212   static Eina_Bool EcoreEventWindowDeleteRequest( void* data, int type, void* event )
213   {
214     EventHandler* handler( (EventHandler*)data );
215     handler->mWindow->mDeleteRequestSignal.Emit();
216     return ECORE_CALLBACK_DONE;
217   }
218
219   // Data
220   Window* mWindow;
221   Ecore_Event_Handler* mWindowPropertyHandler;
222   Ecore_Event_Handler* mClientMessagehandler;
223   Ecore_Event_Handler* mWindowDeleteRequestHandler;
224   Ecore_X_Window mEcoreWindow;
225 };
226
227
228 Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
229 {
230   Window* window = new Window();
231   window->mIsTransparent = isTransparent;
232   window->Initialize( positionSize, name, className );
233   return window;
234 }
235
236 void Window::SetAdaptor(Dali::Adaptor& adaptor)
237 {
238   DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" );
239   mStarted = true;
240
241   // Only create one overlay per window
242   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
243   Integration::Core& core = adaptorImpl.GetCore();
244   mOverlay = &core.GetSystemOverlay();
245
246   Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
247   taskList.CreateTask();
248
249   mAdaptor = &adaptorImpl;
250   mAdaptor->AddObserver( *this );
251
252   // Can only create the detector when we know the Core has been instantiated.
253   mDragAndDropDetector = DragAndDropDetector::New();
254   mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) );
255
256   if( mOrientation )
257   {
258     mOrientation->SetAdaptor(adaptor);
259   }
260
261   if( mIndicator != NULL )
262   {
263     mIndicator->SetAdaptor(mAdaptor);
264   }
265 }
266
267 RenderSurface* Window::GetSurface()
268 {
269   return mSurface;
270 }
271
272 void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode )
273 {
274   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode );
275   DALI_ASSERT_DEBUG(mOverlay);
276
277   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
278   DALI_ASSERT_DEBUG(x11Window);
279   Ecore_X_Window xWinId = x11Window->GetXWindow();
280
281   mIndicatorVisible = visibleMode;
282
283   if ( mIndicatorVisible == Dali::Window::VISIBLE )
284   {
285     // when the indicator is visible, set proper mode for indicator server according to bg mode
286     if ( mIndicatorOpacityMode == Dali::Window::OPAQUE )
287     {
288       ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_OPAQUE);
289     }
290     else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT )
291     {
292       ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_TRANSLUCENT);
293     }
294 #if defined(DALI_PROFILE_MOBILE)
295     else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT )
296     {
297       ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_OPAQUE);
298     }
299 #endif
300   }
301   else
302   {
303     // when the indicator is not visible, set TRANSPARENT mode for indicator server
304     ecore_x_e_illume_indicator_opacity_set(xWinId, ECORE_X_ILLUME_INDICATOR_TRANSPARENT); // it means hidden indicator
305   }
306
307   DoShowIndicator( mIndicatorOrientation );
308 }
309
310 void Window::RotateIndicator(Dali::Window::WindowOrientation orientation)
311 {
312   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation );
313
314   DoRotateIndicator( orientation );
315 }
316
317 void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode )
318 {
319   mIndicatorOpacityMode = opacityMode;
320
321   if( mIndicator != NULL )
322   {
323     mIndicator->SetOpacityMode( opacityMode );
324   }
325 }
326
327 void Window::SetClass(std::string name, std::string klass)
328 {
329   // Get render surface's x11 window
330   if( mSurface )
331   {
332     ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
333     if( x11Window )
334     {
335       ecore_x_icccm_name_class_set( x11Window->GetXWindow(), name.c_str(), klass.c_str() );
336     }
337   }
338 }
339
340 Window::Window()
341 : mSurface( NULL ),
342   mIndicatorVisible( Dali::Window::INVISIBLE ),
343   mIndicatorIsShown( false ),
344   mShowRotatedIndicatorOnClose( false ),
345   mStarted( false ),
346   mIsTransparent( false ),
347   mWMRotationAppSet( false ),
348   mEcoreEventHander( true ),
349   mIsFocusAcceptable( true ),
350   mVisible( true ),
351   mOpaqueState( false ),
352   mResizeEnabled( true ),
353   mIndicator( NULL ),
354   mIndicatorOrientation( Dali::Window::PORTRAIT ),
355   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
356   mIndicatorOpacityMode( Dali::Window::OPAQUE ),
357   mOverlay( NULL ),
358   mAdaptor( NULL ),
359   mType( Dali::DevelWindow::NORMAL ),
360   mEventHandler( NULL ),
361   mPreferredOrientation( Dali::Window::PORTRAIT ),
362   mSupportedAuxiliaryHints(),
363   mAuxiliaryHints(),
364   mIndicatorVisibilityChangedSignal(),
365   mFocusChangedSignal(),
366   mResizedSignal(),
367   mDeleteRequestSignal()
368 {
369
370   // Detect if we're not running in a ecore main loop (e.g. libuv).
371   // Typically ecore_x_init is called by app_efl_main->elm_init
372   // but if we're not using app_efl_main then we have to call it ourselves
373   // This is a hack until we create a pure X Window class
374   if( ecore_x_display_get() == NULL )
375   {
376     mEcoreEventHander = false;
377     ecore_x_init (NULL); //  internally calls _ecore_x_input_init
378   }
379
380 }
381
382 Window::~Window()
383 {
384   delete mEventHandler;
385
386   if( mIndicator )
387   {
388     mOverlay->Remove( mIndicator->GetActor() );
389     Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
390     Dali::RenderTask indicatorTask = taskList.GetTask(0);
391     mOverlay->GetOverlayRenderTasks().RemoveTask(indicatorTask);
392     mIndicator->Close();
393     delete mIndicator;
394   }
395
396   if( mAdaptor )
397   {
398     mAdaptor->RemoveObserver( *this );
399     mAdaptor->SetDragAndDropDetector( NULL );
400     mAdaptor = NULL;
401   }
402
403   delete mSurface;
404 }
405
406 void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
407 {
408   // create an X11 window by default
409   Any surface;
410   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( positionSize, surface, name, className, mIsTransparent );
411   windowSurface->Map();
412
413   mSurface = windowSurface;
414
415   mOrientation = Orientation::New(this);
416
417   // create event handler for X11 window
418   mEventHandler = new EventHandler( this );
419 }
420
421 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
422 {
423   if( mIndicator == NULL )
424   {
425     if( mIndicatorVisible != Dali::Window::INVISIBLE )
426     {
427       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
428       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
429       Dali::Actor actor = mIndicator->GetActor();
430       SetIndicatorActorRotation();
431       mOverlay->Add(actor);
432     }
433     // else don't create a hidden indicator
434   }
435   else // Already have indicator
436   {
437     if( mIndicatorVisible == Dali::Window::VISIBLE )
438     {
439       // If we are resuming, and rotation has changed,
440       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
441       {
442         // then close current indicator and open new one
443         mShowRotatedIndicatorOnClose = true;
444         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
445         // Don't show actor - will contain indicator for old orientation.
446       }
447     }
448   }
449
450   // set indicator visible mode
451   if( mIndicator != NULL )
452   {
453     mIndicator->SetVisible( mIndicatorVisible );
454   }
455
456   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
457   SetIndicatorProperties( show, lastOrientation );
458   mIndicatorIsShown = show;
459 }
460
461 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
462 {
463   if( mIndicatorIsShown )
464   {
465     mShowRotatedIndicatorOnClose = true;
466     mNextIndicatorOrientation = orientation;
467     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
468   }
469   else
470   {
471     // Save orientation for when the indicator is next shown
472     mShowRotatedIndicatorOnClose = false;
473     mNextIndicatorOrientation = orientation;
474   }
475 }
476
477 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
478 {
479   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
480   if( x11Window )
481   {
482     Ecore_X_Window win = x11Window->GetXWindow();
483
484     int show_state = static_cast<int>( isShow );
485     ecore_x_window_prop_property_set( win,
486                                       ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE,
487                                       ECORE_X_ATOM_CARDINAL, 32, &show_state, 1);
488
489     if ( isShow )
490     {
491       ecore_x_e_illume_indicator_state_set(win, ECORE_X_ILLUME_INDICATOR_STATE_ON);
492     }
493     else
494     {
495       ecore_x_e_illume_indicator_state_set(win, ECORE_X_ILLUME_INDICATOR_STATE_OFF);
496     }
497   }
498 }
499
500 void Window::IndicatorTypeChanged(Indicator::Type type)
501 {
502   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
503   if( x11Window )
504   {
505 #ifndef DALI_PROFILE_UBUNTU
506     Ecore_X_Window win = x11Window->GetXWindow();
507     switch(type)
508     {
509       case Indicator::INDICATOR_TYPE_1:
510         ecore_x_e_illume_indicator_type_set( win, ECORE_X_ILLUME_INDICATOR_TYPE_1 );
511         break;
512
513       case Indicator::INDICATOR_TYPE_2:
514         ecore_x_e_illume_indicator_type_set( win, ECORE_X_ILLUME_INDICATOR_TYPE_2 );
515         break;
516
517       case Indicator::INDICATOR_TYPE_UNKNOWN:
518       default:
519         break;
520     }
521 #endif // DALI_PROFILE_UBUNTU
522   }
523 }
524
525 void Window::IndicatorClosed( IndicatorInterface* indicator )
526 {
527   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
528
529   if( mShowRotatedIndicatorOnClose )
530   {
531     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
532     mIndicator->Open(mNextIndicatorOrientation);
533     mIndicatorOrientation = mNextIndicatorOrientation;
534     SetIndicatorActorRotation();
535     DoShowIndicator(currentOrientation);
536   }
537 }
538
539 void Window::IndicatorVisibilityChanged(bool isVisible)
540 {
541   mIndicatorVisibilityChangedSignal.Emit(isVisible);
542 }
543
544 void Window::SetIndicatorActorRotation()
545 {
546   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
547   DALI_ASSERT_DEBUG( mIndicator != NULL );
548
549   Dali::Actor actor = mIndicator->GetActor();
550   switch( mIndicatorOrientation )
551   {
552     case Dali::Window::PORTRAIT:
553       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
554       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
555       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
556       break;
557     case Dali::Window::PORTRAIT_INVERSE:
558       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
559       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
560       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
561       break;
562     case Dali::Window::LANDSCAPE:
563       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
564       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
565       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
566       break;
567     case Dali::Window::LANDSCAPE_INVERSE:
568       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
569       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
570       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
571       break;
572   }
573 }
574
575 void Window::Raise()
576 {
577   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
578   if( x11Window )
579   {
580     Ecore_X_Window win = x11Window->GetXWindow();
581     ecore_x_window_raise(win);
582   }
583 }
584
585 void Window::Lower()
586 {
587   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
588   if( x11Window )
589   {
590     Ecore_X_Window win = x11Window->GetXWindow();
591     ecore_x_window_lower(win);
592   }
593 }
594
595 void Window::Activate()
596 {
597   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
598   if( x11Window )
599   {
600     Ecore_X_Window win = x11Window->GetXWindow();
601     ecore_x_netwm_client_active_request(ecore_x_window_root_get(win), win, 1 /* request type, 1:application, 2:pager */, 0);
602   }
603 }
604
605 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
606 {
607   return mDragAndDropDetector;
608 }
609
610 Dali::Any Window::GetNativeHandle() const
611 {
612   if(mEventHandler)
613   {
614     return mEventHandler->mEcoreWindow;
615   }
616   else
617   {
618     return Dali::Any();
619   }
620 }
621
622 void Window::OnStart()
623 {
624   ShowIndicator( mIndicatorVisible );
625 }
626
627 void Window::OnPause()
628 {
629 }
630
631 void Window::OnResume()
632 {
633   // resume indicator status
634   if( mIndicator != NULL )
635   {
636     // Restore own indicator opacity
637     // Send opacity mode to indicator service when app resumed
638     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
639   }
640 }
641
642 void Window::OnStop()
643 {
644   if( mIndicator )
645   {
646     mIndicator->Close();
647   }
648
649   delete mIndicator;
650   mIndicator = NULL;
651 }
652
653 void Window::OnDestroy()
654 {
655   mAdaptor = NULL;
656 }
657
658 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
659 {
660   bool found = false;
661
662   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
663   {
664     if(mAvailableOrientations[i] == orientation)
665     {
666       found = true;
667       break;
668     }
669   }
670
671   if( ! found )
672   {
673     mAvailableOrientations.push_back(orientation);
674     SetAvailableOrientations( mAvailableOrientations );
675   }
676 }
677
678 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
679 {
680   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
681        iter != mAvailableOrientations.end(); ++iter )
682   {
683     if( *iter == orientation )
684     {
685       mAvailableOrientations.erase( iter );
686       break;
687     }
688   }
689   SetAvailableOrientations( mAvailableOrientations );
690 }
691
692 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
693 {
694   DALI_ASSERT_ALWAYS( mAvailableOrientations.size() <= 4 && "Incorrect number of available orientations" );
695
696   mAvailableOrientations = orientations;
697   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
698   if( x11Window )
699   {
700 #ifndef DALI_PROFILE_UBUNTU
701     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
702     if( ! mWMRotationAppSet )
703     {
704       mWMRotationAppSet = true;
705       ecore_x_e_window_rotation_app_set(ecoreWindow, EINA_TRUE);
706     }
707
708     int rotations[4];
709     for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
710     {
711       rotations[i] = static_cast<int>(mAvailableOrientations[i]);
712     }
713     ecore_x_e_window_rotation_available_rotations_set(ecoreWindow, rotations, mAvailableOrientations.size() );
714 #endif // DALI_PROFILE_UBUNTU
715   }
716 }
717
718 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
719 {
720   return mAvailableOrientations;
721 }
722
723 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
724 {
725   mPreferredOrientation = orientation;
726
727   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
728   if( x11Window )
729   {
730 #ifndef DALI_PROFILE_UBUNTU
731     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
732
733     if( ! mWMRotationAppSet )
734     {
735       mWMRotationAppSet = true;
736       ecore_x_e_window_rotation_app_set(ecoreWindow, EINA_TRUE);
737     }
738
739     ecore_x_e_window_rotation_preferred_rotation_set(ecoreWindow, orientation);
740 #endif // DALI_PROFILE_UBUNTU
741   }
742 }
743
744 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
745 {
746   return mPreferredOrientation;
747 }
748
749 void Window::SetAcceptFocus( bool accept )
750 {
751   mIsFocusAcceptable = accept;
752 }
753
754 bool Window::IsFocusAcceptable()
755 {
756   return mIsFocusAcceptable;
757 }
758
759 void Window::Show()
760 {
761   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
762   if( x11Window )
763   {
764     Ecore_X_Window win = x11Window->GetXWindow();
765     ecore_x_window_show( win );
766
767     // Need an update request
768     if( mAdaptor )
769     {
770       mAdaptor->RequestUpdateOnce();
771     }
772   }
773 }
774
775 void Window::Hide()
776 {
777   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
778   if( x11Window )
779   {
780     Ecore_X_Window win = x11Window->GetXWindow();
781     ecore_x_window_hide( win );
782   }
783 }
784
785 bool Window::IsVisible() const
786 {
787   bool visible = false;
788
789   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
790   if( x11Window )
791   {
792     Ecore_X_Window win = x11Window->GetXWindow();
793     visible = static_cast< bool >( ecore_x_window_visible_get( win ) );
794   }
795   return visible;
796 }
797
798 void Window::RotationDone( int orientation, int width, int height )
799 {
800   // Tell window manager we're done
801   ECore::WindowRenderSurface* x11Window = dynamic_cast< ECore::WindowRenderSurface * >( mSurface );
802   if( x11Window )
803   {
804 #ifndef DALI_PROFILE_UBUNTU
805     Ecore_X_Window ecoreWindow = x11Window->GetXWindow();
806     Ecore_X_Window root = ecore_x_window_root_get(ecoreWindow);
807
808     /**
809      * send rotation done message to wm, even if window is already rotated.
810      * that's why wm must be wait for comming rotation done message
811      * after sending rotation request.
812      */
813     ecore_x_e_window_rotation_change_done_send(root, ecoreWindow, orientation, width, height);
814
815     /**
816      * set rotate window property
817      */
818     int angles[2] = { orientation, orientation };
819     ecore_x_window_prop_property_set( ecoreWindow,
820                                      ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
821                                      ECORE_X_ATOM_CARDINAL, 32, &angles, 2 );
822 #endif // DALI_PROFILE_UBUNTU
823   }
824 }
825
826 unsigned int Window::GetSupportedAuxiliaryHintCount()
827 {
828   return 0;
829 }
830
831 std::string Window::GetSupportedAuxiliaryHint( unsigned int index )
832 {
833   return std::string();
834 }
835
836 unsigned int Window::AddAuxiliaryHint( const std::string& hint, const std::string& value )
837 {
838   return -1;
839 }
840
841 bool Window::RemoveAuxiliaryHint( unsigned int id )
842 {
843   return false;
844 }
845
846 bool Window::SetAuxiliaryHintValue( unsigned int id, const std::string& value )
847 {
848   return false;
849 }
850
851 std::string Window::GetAuxiliaryHintValue( unsigned int id ) const
852 {
853   return std::string();
854 }
855
856 unsigned int Window::GetAuxiliaryHintId( const std::string& hint ) const
857 {
858   return -1;
859 }
860
861 void Window::SetInputRegion( const Rect< int >& inputRegion )
862 {
863 }
864
865 void Window::SetType( Dali::DevelWindow::Type type )
866 {
867   mType = type;
868 }
869
870 Dali::DevelWindow::Type Window::GetType() const
871 {
872   return mType;
873 }
874
875 bool Window::SetNotificationLevel( Dali::DevelWindow::NotificationLevel::Type level )
876 {
877   return false;
878 }
879
880 Dali::DevelWindow::NotificationLevel::Type Window::GetNotificationLevel()
881 {
882   return Dali::DevelWindow::NotificationLevel::NONE;
883 }
884
885 void Window::SetOpaqueState( bool opaque )
886 {
887   mOpaqueState = opaque;
888 }
889
890 bool Window::IsOpaqueState()
891 {
892   return mOpaqueState;
893 }
894
895 bool Window::SetScreenMode( Dali::DevelWindow::ScreenMode::Type screenMode )
896 {
897   return false;
898 }
899
900 Dali::DevelWindow::ScreenMode::Type Window::GetScreenMode()
901 {
902   return Dali::DevelWindow::ScreenMode::DEFAULT;
903 }
904
905 bool Window::SetBrightness( int brightness )
906 {
907   return false;
908 }
909
910 int Window::GetBrightness()
911 {
912   return 0;
913 }
914
915 void Window::SetSize( Dali::DevelWindow::WindowSize size )
916 {
917   PositionSize positionSize = mSurface->GetPositionSize();
918
919   if( positionSize.width != size.GetWidth() || positionSize.height != size.GetHeight() )
920   {
921     positionSize.width = size.GetWidth();
922     positionSize.height = size.GetHeight();
923
924     mSurface->MoveResize( positionSize );
925
926     mAdaptor->SurfaceSizeChanged( Dali::Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
927
928     // Emit signal
929     mResizedSignal.Emit( Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height ) );
930   }
931 }
932
933 Dali::DevelWindow::WindowSize Window::GetSize()
934 {
935   PositionSize positionSize = mSurface->GetPositionSize();
936
937   return Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height );
938 }
939
940 void Window::SetPosition( Dali::DevelWindow::WindowPosition position )
941 {
942   PositionSize positionSize = mSurface->GetPositionSize();
943
944   if( positionSize.x != position.GetX() || positionSize.y != position.GetY() )
945   {
946     positionSize.x = position.GetX();
947     positionSize.y = position.GetY();
948
949     mSurface->MoveResize( positionSize );
950   }
951 }
952
953 Dali::DevelWindow::WindowPosition Window::GetPosition()
954 {
955   PositionSize positionSize = mSurface->GetPositionSize();
956
957   return Dali::DevelWindow::WindowPosition( positionSize.x, positionSize.y );
958 }
959
960 } // Adaptor
961
962 } // Internal
963
964 } // Dali
965
966 #pragma GCC diagnostic pop