Merge "Modify window for rotation event and missed parts." into devel/master
[platform/core/uifw/dali-adaptor.git] / adaptors / ecore / wayland / window-impl-ecore-wl.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_Wayland.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 #include <orientation.h>
30
31 // INTERNAL HEADERS
32 #include <window-render-surface.h>
33 #include <drag-and-drop-detector-impl.h>
34 #include <ecore-indicator-impl.h>
35 #include <window-visibility-observer.h>
36 #include <orientation-impl.h>
37 namespace
38 {
39 const float INDICATOR_ANIMATION_DURATION( 0.18f ); // 180 milli seconds
40 const float INDICATOR_SHOW_Y_POSITION( 0.0f );
41 const float INDICATOR_HIDE_Y_POSITION( -52.0f );
42 }
43
44 namespace Dali
45 {
46 namespace Internal
47 {
48 namespace Adaptor
49 {
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gWindowLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_WINDOW");
52 #endif
53
54 /**
55  * TODO: Abstract Window class out and move this into a window implementation for Ecore
56  */
57 struct Window::EventHandler
58 {
59   /**
60    * Constructor
61    * @param[in]  window  A pointer to the window class.
62    */
63   EventHandler( Window* window )
64   : mWindow( window ),
65     mWindowPropertyHandler( NULL ),
66     mClientMessageHandler( NULL ),
67     mEcoreWindow( 0 )
68   {
69     // store ecore window handle
70     ECore::WindowRenderSurface* wlWindow( dynamic_cast< ECore::WindowRenderSurface * >( mWindow->mSurface ) );
71     if( wlWindow )
72     {
73       mEcoreWindow = wlWindow->GetWlWindow();
74     }
75     DALI_ASSERT_ALWAYS( mEcoreWindow != 0 && "There is no ecore Wl window");
76   }
77
78   /**
79    * Destructor
80    */
81   ~EventHandler()
82   {
83     if ( mWindowPropertyHandler )
84     {
85       ecore_event_handler_del( mWindowPropertyHandler );
86     }
87     if ( mClientMessageHandler )
88     {
89       ecore_event_handler_del( mClientMessageHandler );
90     }
91   }
92
93   // Static methods
94
95   /// Called when the window properties are changed.
96   static Eina_Bool EcoreEventWindowPropertyChanged( void* data, int type, void* event )
97   {
98     return EINA_FALSE;
99   }
100
101   /// Called when the window properties are changed.
102   static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
103   {
104     return EINA_FALSE;
105   }
106
107   // Data
108   Window* mWindow;
109   Ecore_Event_Handler* mWindowPropertyHandler;
110   Ecore_Event_Handler* mClientMessageHandler;
111   Ecore_Wl_Window* mEcoreWindow;
112 };
113
114
115 Window* Window::New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent)
116 {
117   Window* window = new Window();
118   window->mIsTransparent = isTransparent;
119   window->Initialize(posSize, name, className);
120   return window;
121 }
122
123 void Window::SetAdaptor(Dali::Adaptor& adaptor)
124 {
125   DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" );
126   mStarted = true;
127
128   // Only create one overlay per window
129   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
130   Integration::Core& core = adaptorImpl.GetCore();
131   mOverlay = &core.GetSystemOverlay();
132
133   Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
134   taskList.CreateTask();
135
136   mAdaptor = &adaptorImpl;
137   mAdaptor->AddObserver( *this );
138
139   // Can only create the detector when we know the Core has been instantiated.
140   mDragAndDropDetector = DragAndDropDetector::New();
141   mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) );
142
143   if( mOrientation )
144   {
145     mOrientation->SetAdaptor(adaptor);
146   }
147
148   if( mIndicator != NULL )
149   {
150     mIndicator->SetAdaptor(mAdaptor);
151   }
152 }
153
154 RenderSurface* Window::GetSurface()
155 {
156   return mSurface;
157 }
158
159 void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode )
160 {
161   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode );
162   DALI_ASSERT_DEBUG(mOverlay);
163
164   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
165   DALI_ASSERT_DEBUG(wlSurface);
166   Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
167
168   mIndicatorVisible = visibleMode;
169
170   if ( mIndicatorVisible == Dali::Window::VISIBLE )
171   {
172     // when the indicator is visible, set proper mode for indicator server according to bg mode
173     if ( mIndicatorOpacityMode == Dali::Window::OPAQUE )
174     {
175       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
176     }
177     else if ( mIndicatorOpacityMode == Dali::Window::TRANSLUCENT )
178     {
179       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSLUCENT);
180     }
181     else if ( mIndicatorOpacityMode == Dali::Window::TRANSPARENT )
182     {
183       ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_OPAQUE);
184     }
185   }
186   else
187   {
188     // when the indicator is not visible, set TRANSPARENT mode for indicator server
189     ecore_wl_window_indicator_opacity_set(wlWindow, ECORE_WL_INDICATOR_TRANSPARENT); // it means hidden indicator
190   }
191
192   DoShowIndicator( mIndicatorOrientation );
193 }
194
195 void Window::RotateIndicator(Dali::Window::WindowOrientation orientation)
196 {
197   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation );
198
199   DoRotateIndicator( orientation );
200 }
201
202 void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode )
203 {
204   mIndicatorOpacityMode = opacityMode;
205
206   if( mIndicator != NULL )
207   {
208     mIndicator->SetOpacityMode( opacityMode );
209   }
210 }
211
212 void Window::SetClass(std::string name, std::string klass)
213 {
214   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
215
216   if( wlSurface )
217   {
218     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
219     ecore_wl_window_title_set( wlWindow, name.c_str() );
220     ecore_wl_window_class_name_set( wlWindow, klass.c_str() );
221   }
222   else
223   {
224     DALI_LOG_INFO( gWindowLogFilter, Debug::General, "Window has no surface\n" );
225   }
226 }
227
228 Window::Window()
229 : mSurface(NULL),
230   mIndicatorVisible(Dali::Window::VISIBLE),
231   mIndicatorIsShown(false),
232   mShowRotatedIndicatorOnClose(false),
233   mStarted(false),
234   mIsTransparent(false),
235   mWMRotationAppSet(false),
236   mEcoreEventHander(true),
237   mIndicator(NULL),
238   mIndicatorOrientation(Dali::Window::PORTRAIT),
239   mNextIndicatorOrientation(Dali::Window::PORTRAIT),
240   mIndicatorOpacityMode(Dali::Window::OPAQUE),
241   mOverlay(NULL),
242   mAdaptor(NULL),
243   mEventHandler(NULL),
244   mPreferredOrientation(Dali::Window::PORTRAIT)
245 {
246 }
247
248 Window::~Window()
249 {
250   delete mEventHandler;
251
252   if( mIndicator )
253   {
254     mIndicator->Close();
255     delete mIndicator;
256   }
257
258   if ( mAdaptor )
259   {
260     mAdaptor->RemoveObserver( *this );
261     mAdaptor->SetDragAndDropDetector( NULL );
262     mAdaptor = NULL;
263   }
264
265   delete mSurface;
266 }
267
268 void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
269 {
270   // create an Wayland window by default
271   Any surface;
272   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, mIsTransparent );
273
274   mSurface = windowSurface;
275   SetClass( name, className );
276   windowSurface->Map();
277
278   mOrientation = Orientation::New(this);
279
280   // create event handler for Wayland window
281   mEventHandler = new EventHandler( this );
282 }
283
284 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
285 {
286   if( mIndicator == NULL )
287   {
288     if( mIndicatorVisible != Dali::Window::INVISIBLE )
289     {
290       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
291       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
292       Dali::Actor actor = mIndicator->GetActor();
293       SetIndicatorActorRotation();
294       mOverlay->Add(actor);
295     }
296     // else don't create a hidden indicator
297   }
298   else // Already have indicator
299   {
300     if( mIndicatorVisible == Dali::Window::VISIBLE )
301     {
302       // If we are resuming, and rotation has changed,
303       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
304       {
305         // then close current indicator and open new one
306         mShowRotatedIndicatorOnClose = true;
307         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
308         // Don't show actor - will contain indicator for old orientation.
309       }
310     }
311   }
312
313   // set indicator visible mode
314   if( mIndicator != NULL )
315   {
316     mIndicator->SetVisible( mIndicatorVisible );
317   }
318
319   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
320   SetIndicatorProperties( show, lastOrientation );
321   mIndicatorIsShown = show;
322 }
323
324 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
325 {
326   if( mIndicatorIsShown )
327   {
328     mShowRotatedIndicatorOnClose = true;
329     mNextIndicatorOrientation = orientation;
330     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
331   }
332   else
333   {
334     // Save orientation for when the indicator is next shown
335     mShowRotatedIndicatorOnClose = false;
336     mNextIndicatorOrientation = orientation;
337   }
338 }
339
340 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
341 {
342   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
343
344   if( wlSurface )
345   {
346     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
347     if ( isShow )
348     {
349       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_ON);
350     }
351     else
352     {
353       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_OFF);
354     }
355   }
356 }
357
358 void Window::IndicatorTypeChanged(Indicator::Type type)
359 {
360 #if defined(DALI_PROFILE_MOBILE)
361   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
362
363   if( wlSurface )
364   {
365     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
366     switch(type)
367     {
368       case Indicator::INDICATOR_TYPE_1:
369         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
370         break;
371
372       case Indicator::INDICATOR_TYPE_2:
373         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
374         break;
375
376       case Indicator::INDICATOR_TYPE_UNKNOWN:
377       default:
378         break;
379     }
380   }
381 #endif //MOBILE
382 }
383
384 void Window::IndicatorClosed( IndicatorInterface* indicator )
385 {
386   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
387
388   if( mShowRotatedIndicatorOnClose )
389   {
390     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
391     mIndicator->Open(mNextIndicatorOrientation);
392     mIndicatorOrientation = mNextIndicatorOrientation;
393     SetIndicatorActorRotation();
394     DoShowIndicator(currentOrientation);
395   }
396 }
397
398 void Window::IndicatorVisibilityChanged(bool isVisible)
399 {
400   mIndicatorVisibilityChangedSignal.Emit(isVisible);
401 }
402
403 void Window::SetIndicatorActorRotation()
404 {
405   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
406   DALI_ASSERT_DEBUG( mIndicator != NULL );
407
408   Dali::Actor actor = mIndicator->GetActor();
409   switch( mIndicatorOrientation )
410   {
411     case Dali::Window::PORTRAIT:
412       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
413       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
414       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
415       break;
416     case Dali::Window::PORTRAIT_INVERSE:
417       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
418       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
419       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
420       break;
421     case Dali::Window::LANDSCAPE:
422       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
423       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
424       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
425       break;
426     case Dali::Window::LANDSCAPE_INVERSE:
427       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
428       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
429       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
430       break;
431   }
432 }
433
434 void Window::Raise()
435 {
436   ecore_wl_window_raise( mEventHandler->mEcoreWindow );
437 }
438
439 void Window::Lower()
440 {
441   ecore_wl_window_lower( mEventHandler->mEcoreWindow );
442 }
443
444 void Window::Activate()
445 {
446   ecore_wl_window_activate( mEventHandler->mEcoreWindow );
447 }
448
449 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
450 {
451   return mDragAndDropDetector;
452 }
453
454 Dali::Any Window::GetNativeHandle() const
455 {
456   if(mEventHandler)
457   {
458     return mEventHandler->mEcoreWindow;
459   }
460   else
461   {
462     return Dali::Any();
463   }
464 }
465
466 void Window::OnStart()
467 {
468   DoShowIndicator( mIndicatorOrientation );
469 }
470
471 void Window::OnPause()
472 {
473 }
474
475 void Window::OnResume()
476 {
477   // resume indicator status
478   if( mIndicator != NULL )
479   {
480     // Restore own indicator opacity
481     // Send opacity mode to indicator service when app resumed
482     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
483   }
484 }
485
486 void Window::OnStop()
487 {
488   if( mIndicator )
489   {
490     mIndicator->Close();
491   }
492
493   delete mIndicator;
494   mIndicator = NULL;
495 }
496
497 void Window::OnDestroy()
498 {
499   mAdaptor = NULL;
500 }
501
502 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
503 {
504   bool found = false;
505
506   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
507   {
508     if(mAvailableOrientations[i] == orientation)
509     {
510       found = true;
511       break;
512     }
513   }
514
515   if( ! found )
516   {
517     mAvailableOrientations.push_back(orientation);
518     SetAvailableOrientations( mAvailableOrientations );
519   }
520 }
521
522 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
523 {
524   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
525        iter != mAvailableOrientations.end(); ++iter )
526   {
527     if( *iter == orientation )
528     {
529       mAvailableOrientations.erase( iter );
530       break;
531     }
532   }
533   SetAvailableOrientations( mAvailableOrientations );
534 }
535
536 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
537 {
538   int rotations[4];
539   for( std::size_t i = 0; i < mAvailableOrientations.size(); ++i )
540   {
541     rotations[i] = static_cast< int >( mAvailableOrientations[i] );
542   }
543   ecore_wl_window_rotation_available_rotations_set( mEventHandler->mEcoreWindow, rotations, mAvailableOrientations.size() );
544 }
545
546 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
547 {
548   return mAvailableOrientations;
549 }
550
551 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
552 {
553   mPreferredOrientation = orientation;
554
555   ecore_wl_window_rotation_preferred_rotation_set( mEventHandler->mEcoreWindow, orientation );
556 }
557
558 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
559 {
560   return mPreferredOrientation;
561 }
562
563 void Window::RotationDone( int orientation, int width, int height )
564 {
565   ecore_wl_window_rotation_change_done_send( mEventHandler->mEcoreWindow );
566 }
567
568
569 } // Adaptor
570 } // Internal
571 } // Dali