Fix crash in wayland
[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
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     mEcoreWindow( 0 )
69   {
70   }
71
72   /**
73    * Destructor
74    */
75   ~EventHandler()
76   {
77     if ( mWindowPropertyHandler )
78     {
79       ecore_event_handler_del( mWindowPropertyHandler );
80     }
81     if ( mClientMessageHandler )
82     {
83       ecore_event_handler_del( mClientMessageHandler );
84     }
85   }
86
87   // Static methods
88
89   /// Called when the window properties are changed.
90   static Eina_Bool EcoreEventWindowPropertyChanged( void* data, int type, void* event )
91   {
92     return EINA_FALSE;
93   }
94
95   /// Called when the window properties are changed.
96   static Eina_Bool EcoreEventClientMessage( void* data, int type, void* event )
97   {
98     return EINA_FALSE;
99   }
100
101   // Data
102   Window* mWindow;
103   Ecore_Event_Handler* mWindowPropertyHandler;
104   Ecore_Event_Handler* mClientMessageHandler;
105   Ecore_Wl_Window* mEcoreWindow;
106 };
107
108
109 Window* Window::New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent)
110 {
111   Window* window = new Window();
112   window->mIsTransparent = isTransparent;
113   window->Initialize(posSize, name, className);
114   return window;
115 }
116
117 void Window::SetAdaptor(Dali::Adaptor& adaptor)
118 {
119   DALI_ASSERT_ALWAYS( !mStarted && "Adaptor already started" );
120   mStarted = true;
121
122   // Only create one overlay per window
123   Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
124   Integration::Core& core = adaptorImpl.GetCore();
125   mOverlay = &core.GetSystemOverlay();
126
127   Dali::RenderTaskList taskList = mOverlay->GetOverlayRenderTasks();
128   taskList.CreateTask();
129
130   mAdaptor = &adaptorImpl;
131   mAdaptor->AddObserver( *this );
132
133   // Can only create the detector when we know the Core has been instantiated.
134   mDragAndDropDetector = DragAndDropDetector::New();
135   mAdaptor->SetDragAndDropDetector( &GetImplementation( mDragAndDropDetector ) );
136
137   if( mOrientation )
138   {
139     mOrientation->SetAdaptor(adaptor);
140   }
141
142   if( mIndicator != NULL )
143   {
144     mIndicator->SetAdaptor(mAdaptor);
145   }
146 }
147
148 RenderSurface* Window::GetSurface()
149 {
150   return mSurface;
151 }
152
153 void Window::ShowIndicator( Dali::Window::IndicatorVisibleMode visibleMode )
154 {
155   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "visible : %d\n", visibleMode );
156   DALI_ASSERT_DEBUG(mOverlay);
157
158   DoShowIndicator( mIndicatorOrientation );
159 }
160
161 void Window::RotateIndicator(Dali::Window::WindowOrientation orientation)
162 {
163   DALI_LOG_TRACE_METHOD_FMT( gWindowLogFilter, "Orientation: %d\n", orientation );
164
165   DoRotateIndicator( orientation );
166 }
167
168 void Window::SetIndicatorBgOpacity( Dali::Window::IndicatorBgOpacity opacityMode )
169 {
170   mIndicatorOpacityMode = opacityMode;
171
172   if( mIndicator != NULL )
173   {
174     mIndicator->SetOpacityMode( opacityMode );
175   }
176 }
177
178 void Window::SetClass(std::string name, std::string klass)
179 {
180 }
181
182 Window::Window()
183 : mSurface(NULL),
184   mIndicatorVisible(Dali::Window::VISIBLE),
185   mIndicatorIsShown(false),
186   mShowRotatedIndicatorOnClose(false),
187   mStarted(false),
188   mIsTransparent(false),
189   mWMRotationAppSet(false),
190   mIndicator(NULL),
191   mIndicatorOrientation(Dali::Window::PORTRAIT),
192   mNextIndicatorOrientation(Dali::Window::PORTRAIT),
193   mIndicatorOpacityMode(Dali::Window::OPAQUE),
194   mOverlay(NULL),
195   mAdaptor(NULL),
196   mEventHandler(NULL),
197   mPreferredOrientation(Dali::Window::PORTRAIT)
198 {
199 }
200
201 Window::~Window()
202 {
203   delete mEventHandler;
204
205   if( mIndicator )
206   {
207     mIndicator->Close();
208     delete mIndicator;
209   }
210
211   if ( mAdaptor )
212   {
213     mAdaptor->RemoveObserver( *this );
214     mAdaptor->SetDragAndDropDetector( NULL );
215     mAdaptor = NULL;
216   }
217
218   delete mSurface;
219 }
220
221 void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
222 {
223   // create an Wayland window by default
224   Any surface;
225   ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, mIsTransparent );
226   SetClass( name, className );
227   windowSurface->Map();
228
229   mSurface = windowSurface;
230
231   mOrientation = Orientation::New(this);
232
233   // create event handler for Wayland window
234   mEventHandler = new EventHandler( this );
235 }
236
237 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
238 {
239   if( mIndicator == NULL )
240   {
241     if( mIndicatorVisible != Dali::Window::INVISIBLE )
242     {
243       mIndicator = new Indicator( mAdaptor, mIndicatorOrientation, this );
244       mIndicator->SetOpacityMode( mIndicatorOpacityMode );
245       Dali::Actor actor = mIndicator->GetActor();
246       SetIndicatorActorRotation();
247       mOverlay->Add(actor);
248     }
249     // else don't create a hidden indicator
250   }
251   else // Already have indicator
252   {
253     if( mIndicatorVisible == Dali::Window::VISIBLE )
254     {
255       // If we are resuming, and rotation has changed,
256       if( mIndicatorIsShown == false && mIndicatorOrientation != mNextIndicatorOrientation )
257       {
258         // then close current indicator and open new one
259         mShowRotatedIndicatorOnClose = true;
260         mIndicator->Close(); // May synchronously call IndicatorClosed() callback & 1 level of recursion
261         // Don't show actor - will contain indicator for old orientation.
262       }
263     }
264   }
265
266   // set indicator visible mode
267   if( mIndicator != NULL )
268   {
269     mIndicator->SetVisible( mIndicatorVisible );
270   }
271
272   bool show = (mIndicatorVisible != Dali::Window::INVISIBLE );
273   SetIndicatorProperties( show, lastOrientation );
274   mIndicatorIsShown = show;
275 }
276
277 void Window::DoRotateIndicator( Dali::Window::WindowOrientation orientation )
278 {
279   if( mIndicatorIsShown )
280   {
281     mShowRotatedIndicatorOnClose = true;
282     mNextIndicatorOrientation = orientation;
283     mIndicator->Close(); // May synchronously call IndicatorClosed() callback
284   }
285   else
286   {
287     // Save orientation for when the indicator is next shown
288     mShowRotatedIndicatorOnClose = false;
289     mNextIndicatorOrientation = orientation;
290   }
291 }
292
293 void Window::SetIndicatorProperties( bool isShow, Dali::Window::WindowOrientation lastOrientation )
294 {
295 }
296
297 void Window::IndicatorTypeChanged(Indicator::Type type)
298 {
299 }
300
301 void Window::IndicatorClosed( IndicatorInterface* indicator )
302 {
303   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
304
305   if( mShowRotatedIndicatorOnClose )
306   {
307     Dali::Window::WindowOrientation currentOrientation = mIndicatorOrientation;
308     mIndicator->Open(mNextIndicatorOrientation);
309     mIndicatorOrientation = mNextIndicatorOrientation;
310     SetIndicatorActorRotation();
311     DoShowIndicator(currentOrientation);
312   }
313 }
314
315 void Window::IndicatorVisibilityChanged(bool isVisible)
316 {
317   mIndicatorVisibilityChangedSignal.Emit(isVisible);
318 }
319
320 void Window::SetIndicatorActorRotation()
321 {
322   DALI_LOG_TRACE_METHOD( gWindowLogFilter );
323   DALI_ASSERT_DEBUG( mIndicator != NULL );
324
325   Dali::Actor actor = mIndicator->GetActor();
326   switch( mIndicatorOrientation )
327   {
328     case Dali::Window::PORTRAIT:
329       actor.SetParentOrigin( ParentOrigin::TOP_CENTER );
330       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
331       actor.SetOrientation( Degree(0), Vector3::ZAXIS );
332       break;
333     case Dali::Window::PORTRAIT_INVERSE:
334       actor.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
335       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
336       actor.SetOrientation( Degree(180), Vector3::ZAXIS );
337       break;
338     case Dali::Window::LANDSCAPE:
339       actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
340       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
341       actor.SetOrientation( Degree(270), Vector3::ZAXIS );
342       break;
343     case Dali::Window::LANDSCAPE_INVERSE:
344       actor.SetParentOrigin( ParentOrigin::CENTER_RIGHT );
345       actor.SetAnchorPoint(  AnchorPoint::TOP_CENTER );
346       actor.SetOrientation( Degree(90), Vector3::ZAXIS );
347       break;
348   }
349 }
350
351 void Window::Raise()
352 {
353 }
354
355 void Window::Lower()
356 {
357 }
358
359 void Window::Activate()
360 {
361 }
362
363 Dali::DragAndDropDetector Window::GetDragAndDropDetector() const
364 {
365   return mDragAndDropDetector;
366 }
367
368 Dali::Any Window::GetNativeHandle() const
369 {
370   if(mEventHandler)
371   {
372     return mEventHandler->mEcoreWindow;
373   }
374   else
375   {
376     return Dali::Any();
377   }
378 }
379
380 void Window::OnStart()
381 {
382   DoShowIndicator( mIndicatorOrientation );
383 }
384
385 void Window::OnPause()
386 {
387 }
388
389 void Window::OnResume()
390 {
391   // resume indicator status
392   if( mIndicator != NULL )
393   {
394     // Restore own indicator opacity
395     // Send opacity mode to indicator service when app resumed
396     mIndicator->SetOpacityMode( mIndicatorOpacityMode );
397   }
398 }
399
400 void Window::OnStop()
401 {
402   if( mIndicator )
403   {
404     mIndicator->Close();
405   }
406
407   delete mIndicator;
408   mIndicator = NULL;
409 }
410
411 void Window::OnDestroy()
412 {
413   mAdaptor = NULL;
414 }
415
416 void Window::AddAvailableOrientation(Dali::Window::WindowOrientation orientation)
417 {
418   bool found = false;
419
420   for( std::size_t i=0; i<mAvailableOrientations.size(); i++ )
421   {
422     if(mAvailableOrientations[i] == orientation)
423     {
424       found = true;
425       break;
426     }
427   }
428
429   if( ! found )
430   {
431     mAvailableOrientations.push_back(orientation);
432     SetAvailableOrientations( mAvailableOrientations );
433   }
434 }
435
436 void Window::RemoveAvailableOrientation(Dali::Window::WindowOrientation orientation)
437 {
438   for( std::vector<Dali::Window::WindowOrientation>::iterator iter = mAvailableOrientations.begin();
439        iter != mAvailableOrientations.end(); ++iter )
440   {
441     if( *iter == orientation )
442     {
443       mAvailableOrientations.erase( iter );
444       break;
445     }
446   }
447   SetAvailableOrientations( mAvailableOrientations );
448 }
449
450 void Window::SetAvailableOrientations(const std::vector<Dali::Window::WindowOrientation>& orientations)
451 {
452   DALI_ASSERT_ALWAYS( mAvailableOrientations.size() <= 4 && "Incorrect number of available orientations" );
453 }
454
455 const std::vector<Dali::Window::WindowOrientation>& Window::GetAvailableOrientations()
456 {
457   return mAvailableOrientations;
458 }
459
460 void Window::SetPreferredOrientation(Dali::Window::WindowOrientation orientation)
461 {
462   mPreferredOrientation = orientation;
463 }
464
465 Dali::Window::WindowOrientation Window::GetPreferredOrientation()
466 {
467   return mPreferredOrientation;
468 }
469
470 void Window::RotationDone( int orientation, int width, int height )
471 {
472 }
473
474
475 } // Adaptor
476 } // Internal
477 } // Dali