Implement wayland indicator AUTO mode
[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 }
215
216 Window::Window()
217 : mSurface(NULL),
218   mIndicatorVisible(Dali::Window::VISIBLE),
219   mIndicatorIsShown(false),
220   mShowRotatedIndicatorOnClose(false),
221   mStarted(false),
222   mIsTransparent(false),
223   mWMRotationAppSet(false),
224   mIndicator(NULL),
225   mIndicatorOrientation(Dali::Window::PORTRAIT),
226   mNextIndicatorOrientation(Dali::Window::PORTRAIT),
227   mIndicatorOpacityMode(Dali::Window::OPAQUE),
228   mOverlay(NULL),
229   mAdaptor(NULL),
230   mEventHandler(NULL),
231   mPreferredOrientation(Dali::Window::PORTRAIT)
232 {
233 }
234
235 Window::~Window()
236 {
237   delete mEventHandler;
238
239   if( mIndicator )
240   {
241     mIndicator->Close();
242     delete mIndicator;
243   }
244
245   if ( mAdaptor )
246   {
247     mAdaptor->RemoveObserver( *this );
248     mAdaptor->SetDragAndDropDetector( NULL );
249     mAdaptor = NULL;
250   }
251
252   delete mSurface;
253 }
254
255 void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
256 {
257   // create an Wayland window by default
258   Any surface;
259   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, mIsTransparent );
260   SetClass( name, className );
261   windowSurface->Map();
262
263   mSurface = windowSurface;
264
265   std::string appId;
266   mAdaptor->GetAppId( appId );
267   Ecore_Wl_Window* wlWindow = windowSurface ->GetWlWindow();
268   ecore_wl_window_class_name_set(wlWindow, appId.c_str());
269
270   mOrientation = Orientation::New(this);
271
272   // create event handler for Wayland window
273   mEventHandler = new EventHandler( this );
274 }
275
276 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
277 {
278   if( mIndicator == NULL )
279   {
280     if( mIndicatorVisible != Dali::Window::INVISIBLE )
281     {
282       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
283       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
284       Dali::Actor actor = mIndicator->GetActor();
285       SetIndicatorActorRotation();
286       mOverlay->Add(actor);
287     }
288     // else don't create a hidden indicator
289   }
290   else // Already have indicator
291   {
292     if( mIndicatorVisible == Dali::Window::VISIBLE )
293     {
294       // If we are resuming, and rotation has changed,
295       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
296       {
297         // then close current indicator and open new one
298         mShowRotatedIndicatorOnClose = true;
299         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
300         // Don't show actor - will contain indicator for old orientation.
301       }
302     }
303   }
304
305   // set indicator visible mode
306   if( mIndicator != NULL )
307   {
308     mIndicator->SetVisible( mIndicatorVisible );
309   }
310
311   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
312   SetIndicatorProperties( show, lastOrientation );
313   mIndicatorIsShown = show;
314 }
315
316 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
317 {
318   if( mIndicatorIsShown )
319   {
320     mShowRotatedIndicatorOnClose = true;
321     mNextIndicatorOrientation = orientation;
322     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
323   }
324   else
325   {
326     // Save orientation for when the indicator is next shown
327     mShowRotatedIndicatorOnClose = false;
328     mNextIndicatorOrientation = orientation;
329   }
330 }
331
332 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
333 {
334   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
335
336   if( wlSurface )
337   {
338     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
339     if ( isShow )
340     {
341       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_ON);
342     }
343     else
344     {
345       ecore_wl_window_indicator_state_set(wlWindow, ECORE_WL_INDICATOR_STATE_OFF);
346     }
347   }
348 }
349
350 void Window::IndicatorTypeChanged(Indicator::Type type)
351 {
352   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
353
354   if( wlSurface )
355   {
356     Ecore_Wl_Window* wlWindow = wlSurface->GetWlWindow();
357     switch(type)
358     {
359       case Indicator::INDICATOR_TYPE_1:
360         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
361         break;
362
363       case Indicator::INDICATOR_TYPE_2:
364         ecore_wl_indicator_visible_type_set(wlWindow, ECORE_WL_INDICATOR_VISIBLE_TYPE_HIDDEN);
365         break;
366
367       case Indicator::INDICATOR_TYPE_UNKNOWN:
368       default:
369         break;
370     }
371   }
372 }
373
374 void Window::IndicatorClosed( IndicatorInterface* indicator )
375 {
376   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
377
378   if( mShowRotatedIndicatorOnClose )
379   {
380     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
381     mIndicator->Open(mNextIndicatorOrientation);
382     mIndicatorOrientation = mNextIndicatorOrientation;
383     SetIndicatorActorRotation();
384     DoShowIndicator(currentOrientation);
385   }
386 }
387
388 void Window::IndicatorVisibilityChanged(bool isVisible)
389 {
390   mIndicatorVisibilityChangedSignal.Emit(isVisible);
391 }
392
393 void Window::SetIndicatorActorRotation()
394 {
395   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
396   DALI_ASSERT_DEBUG( mIndicator != NULL );
397
398   Dali::Actor actor = mIndicator->GetActor();
399   switch( mIndicatorOrientation )
400   {
401     case Dali::Window::PORTRAIT:
402       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
403       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
404       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
405       break;
406     case Dali::Window::PORTRAIT_INVERSE:
407       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
408       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
409       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
410       break;
411     case Dali::Window::LANDSCAPE:
412       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
413       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
414       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
415       break;
416     case Dali::Window::LANDSCAPE_INVERSE:
417       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
418       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
419       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
420       break;
421   }
422 }
423
424 void Window::Raise()
425 {
426 }
427
428 void Window::Lower()
429 {
430 }
431
432 void Window::Activate()
433 {
434 }
435
436 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
437 {
438   return mDragAndDropDetector;
439 }
440
441 Dali::Any Window::GetNativeHandle() const
442 {
443   if(mEventHandler)
444   {
445     return mEventHandler->mEcoreWindow;
446   }
447   else
448   {
449     return Dali::Any();
450   }
451 }
452
453 void Window::OnStart()
454 {
455   DoShowIndicator( mIndicatorOrientation );
456 }
457
458 void Window::OnPause()
459 {
460 }
461
462 void Window::OnResume()
463 {
464   // resume indicator status
465   if( mIndicator != NULL )
466   {
467     // Restore own indicator opacity
468     // Send opacity mode to indicator service when app resumed
469     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
470   }
471 }
472
473 void Window::OnStop()
474 {
475   if( mIndicator )
476   {
477     mIndicator->Close();
478   }
479
480   delete mIndicator;
481   mIndicator = NULL;
482 }
483
484 void Window::OnDestroy()
485 {
486   mAdaptor = NULL;
487 }
488
489 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
490 {
491   bool found = false;
492
493   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
494   {
495     if(mAvailableOrientations[i] == orientation)
496     {
497       found = true;
498       break;
499     }
500   }
501
502   if( ! found )
503   {
504     mAvailableOrientations.push_back(orientation);
505     SetAvailableOrientations( mAvailableOrientations );
506   }
507 }
508
509 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
510 {
511   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
512        iter != mAvailableOrientations.end(); ++iter )
513   {
514     if( *iter == orientation )
515     {
516       mAvailableOrientations.erase( iter );
517       break;
518     }
519   }
520   SetAvailableOrientations( mAvailableOrientations );
521 }
522
523 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
524 {
525   DALI_ASSERT_ALWAYS( mAvailableOrientations.size() <= 4 && "Incorrect number of available orientations" );
526 }
527
528 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
529 {
530   return mAvailableOrientations;
531 }
532
533 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
534 {
535   mPreferredOrientation = orientation;
536 }
537
538 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
539 {
540   return mPreferredOrientation;
541 }
542
543 void Window::RotationDone( int orientation, int width, int height )
544 {
545 }
546
547
548 } // Adaptor
549 } // Internal
550 } // Dali