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