Move key grab implementation to window
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / tizen-wayland / window-render-surface-ecore-wl.cpp
1 /*
2  * Copyright (c) 2018 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 <dali/internal/window-system/tizen-wayland/window-render-surface-ecore-wl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/gl-abstraction.h>
23 #include <dali/integration-api/debug.h>
24
25 // INTERNAL INCLUDES
26 #include <dali/internal/window-system/tizen-wayland/wl-types.h>
27 #include <dali/internal/graphics/gles20/egl-implementation.h>
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/integration-api/trigger-event-factory-interface.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 namespace Adaptor
36 {
37
38 namespace
39 {
40
41 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
42
43 #if defined(DEBUG_ENABLED)
44 Debug::Filter* gWindowRenderSurfaceLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_WINDOW_RENDER_SURFACE_ECORE_WL");
45 #endif
46
47 } // unnamed namespace
48
49 WindowRenderSurfaceEcoreWl::WindowRenderSurfaceEcoreWl( Dali::PositionSize positionSize,
50                                                         Any surface,
51                                                         const std::string& name,
52                                                         bool isTransparent)
53 : mTitle( name ),
54   mPositionSize( positionSize ),
55   mWlWindow( NULL ),
56   mWlSurface( NULL ),
57   mEglWindow( NULL ),
58   mThreadSynchronization( NULL ),
59   mRenderNotification( NULL ),
60   mRotationTrigger( NULL ),
61   mColorDepth( isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24 ),
62   mRotationAngle( 0 ),
63   mScreenRotationAngle( 0 ),
64   mOwnSurface( false ),
65   mRotationSupported( false ),
66   mRotationFinished( true ),
67   mScreenRotationFinished( true ),
68   mResizeFinished( true )
69 {
70   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
71   Initialize( surface );
72 }
73
74 WindowRenderSurfaceEcoreWl::~WindowRenderSurfaceEcoreWl()
75 {
76   if( mEglWindow != NULL )
77   {
78     wl_egl_window_destroy(mEglWindow);
79     mEglWindow = NULL;
80   }
81
82   if( mOwnSurface )
83   {
84     ecore_wl_window_free( mWlWindow );
85   }
86
87   if( mRotationTrigger )
88   {
89     delete mRotationTrigger;
90   }
91
92   if( mOwnSurface )
93   {
94     ecore_wl_shutdown();
95   }
96 }
97
98 void WindowRenderSurfaceEcoreWl::Initialize( Any surface )
99 {
100   // see if there is a surface in Any surface
101   unsigned int surfaceId = GetSurfaceId( surface );
102
103   // if the surface is empty, create a new one.
104   if( surfaceId == 0 )
105   {
106     // we own the surface about to created
107     ecore_wl_init( NULL );
108     mOwnSurface = true;
109     CreateRenderable();
110   }
111   else
112   {
113     // XLib should already be initialized so no point in calling XInitThreads
114     UseExistingRenderable( surfaceId );
115   }
116 }
117
118 Ecore_Wl_Window* WindowRenderSurfaceEcoreWl::GetWlWindow()
119 {
120   return mWlWindow;
121 }
122
123 void WindowRenderSurfaceEcoreWl::OutputTransformed()
124 {
125   int transform;
126
127   if( ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
128   {
129     transform = 0;
130   }
131   else
132   {
133     transform = ecore_wl_output_transform_get( ecore_wl_window_output_find( mWlWindow ) );
134   }
135
136   mScreenRotationAngle = transform * 90;
137   mScreenRotationFinished = false;
138
139   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::OutputTransformed: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
140 }
141
142 Any WindowRenderSurfaceEcoreWl::GetWindow()
143 {
144   return mWlWindow;
145 }
146
147 void WindowRenderSurfaceEcoreWl::Map()
148 {
149   ecore_wl_window_show( mWlWindow );
150 }
151
152 void WindowRenderSurfaceEcoreWl::SetRenderNotification( TriggerEventInterface* renderNotification )
153 {
154   mRenderNotification = renderNotification;
155 }
156
157 void WindowRenderSurfaceEcoreWl::SetTransparency( bool transparent )
158 {
159   ecore_wl_window_alpha_set( mWlWindow, transparent );
160 }
161
162 void WindowRenderSurfaceEcoreWl::RequestRotation( int angle, int width, int height )
163 {
164   if( !mRotationSupported )
165   {
166     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::Rotate: Rotation is not supported!\n" );
167     return;
168   }
169
170   if( !mRotationTrigger )
171   {
172     TriggerEventFactoryInterface& triggerFactory = Internal::Adaptor::Adaptor::GetImplementation( Adaptor::Get() ).GetTriggerEventFactoryInterface();
173     mRotationTrigger = triggerFactory.CreateTriggerEvent( MakeCallback( this, &WindowRenderSurfaceEcoreWl::ProcessRotationRequest ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER );
174   }
175
176   mPositionSize.width = width;
177   mPositionSize.height = height;
178
179   mRotationAngle = angle;
180   mRotationFinished = false;
181
182   ecore_wl_window_rotation_set( mWlWindow, mRotationAngle );
183
184   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::Rotate: angle = %d screen rotation = %d\n", mRotationAngle, mScreenRotationAngle );
185 }
186
187 PositionSize WindowRenderSurfaceEcoreWl::GetPositionSize() const
188 {
189   return mPositionSize;
190 }
191
192 void WindowRenderSurfaceEcoreWl::InitializeEgl( EglInterface& eglIf )
193 {
194   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
195
196   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
197
198   eglImpl.ChooseConfig(true, mColorDepth);
199 }
200
201 void WindowRenderSurfaceEcoreWl::CreateEglSurface( EglInterface& eglIf )
202 {
203   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
204
205   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
206
207   // create the EGL window
208   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
209   {
210     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
211   }
212   else
213   {
214     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
215   }
216
217   EGLNativeWindowType windowType( mEglWindow );
218   eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
219
220   // Check capability
221   wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
222   if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
223   {
224     DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::CreateEglSurface: capability = %d\n", capability );
225     mRotationSupported = true;
226   }
227
228   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::CreateEglSurface: w = %d h = %d angle = %d screen rotation = %d\n", mPositionSize.width, mPositionSize.height, mRotationAngle, mScreenRotationAngle );
229 }
230
231 void WindowRenderSurfaceEcoreWl::DestroyEglSurface( EglInterface& eglIf )
232 {
233   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
234
235   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
236   eglImpl.DestroySurface();
237
238   if( mEglWindow != NULL )
239   {
240     wl_egl_window_destroy(mEglWindow);
241     mEglWindow = NULL;
242   }
243 }
244
245 bool WindowRenderSurfaceEcoreWl::ReplaceEGLSurface( EglInterface& egl )
246 {
247   DALI_LOG_TRACE_METHOD( gWindowRenderSurfaceLogFilter );
248
249   if( mEglWindow != NULL )
250   {
251     wl_egl_window_destroy(mEglWindow);
252     mEglWindow = NULL;
253   }
254
255   if( mScreenRotationAngle == 0 || mScreenRotationAngle == 180 )
256   {
257     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.width, mPositionSize.height );
258   }
259   else
260   {
261     mEglWindow = wl_egl_window_create( mWlSurface, mPositionSize.height, mPositionSize.width );
262   }
263
264   // Set screen rotation
265   mScreenRotationFinished = false;
266
267   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
268   EGLNativeWindowType windowType( mEglWindow );
269   return eglImpl.ReplaceSurfaceWindow( windowType );
270 }
271
272 void WindowRenderSurfaceEcoreWl::MoveResize( Dali::PositionSize positionSize )
273 {
274   bool needToMove = false;
275   bool needToResize = false;
276
277   // check moving
278   if( (fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
279       (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE) )
280   {
281     needToMove = true;
282   }
283
284   // check resizing
285   if( (fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
286       (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE) )
287   {
288     needToResize = true;
289   }
290
291   if( needToMove )
292   {
293     ecore_wl_window_position_set( mWlWindow, positionSize.x, positionSize.y );
294   }
295   if( needToResize )
296   {
297     ecore_wl_window_update_size( mWlWindow, positionSize.width, positionSize.height );
298     mResizeFinished = false;
299   }
300
301   mPositionSize = positionSize;
302
303   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height );
304 }
305
306 void WindowRenderSurfaceEcoreWl::SetViewMode( ViewMode viewMode )
307 {
308 }
309
310 void WindowRenderSurfaceEcoreWl::StartRender()
311 {
312 }
313
314 bool WindowRenderSurfaceEcoreWl::PreRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, bool resizingSurface )
315 {
316   if( resizingSurface )
317   {
318 #ifdef OVER_TIZEN_VERSION_4
319     // Window rotate or screen rotate
320     if( !mRotationFinished || !mScreenRotationFinished )
321     {
322       wl_egl_window_rotation rotation;
323       wl_output_transform bufferTransform;
324       int totalAngle = (mRotationAngle + mScreenRotationAngle) % 360;
325
326       switch( totalAngle )
327       {
328         case 0:
329         {
330           rotation = ROTATION_0;
331           bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
332           break;
333         }
334         case 90:
335         {
336           rotation = ROTATION_270;
337           bufferTransform = WL_OUTPUT_TRANSFORM_90;
338           break;
339         }
340         case 180:
341         {
342           rotation = ROTATION_180;
343           bufferTransform = WL_OUTPUT_TRANSFORM_180;
344           break;
345         }
346         case 270:
347         {
348           rotation = ROTATION_90;
349           bufferTransform = WL_OUTPUT_TRANSFORM_270;
350           break;
351         }
352         default:
353         {
354           rotation = ROTATION_0;
355           bufferTransform = WL_OUTPUT_TRANSFORM_NORMAL;
356           break;
357         }
358       }
359
360       wl_egl_window_set_rotation( mEglWindow, rotation );
361
362       wl_egl_window_set_buffer_transform( mEglWindow, bufferTransform );
363
364       // Reset only screen rotation flag
365       mScreenRotationFinished = true;
366
367       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::PreRender: Set rotation [%d] [%d]\n", mRotationAngle, mScreenRotationAngle );
368     }
369
370     // Only window rotate
371     if( !mRotationFinished )
372     {
373       wl_output_transform windowTransform;
374
375       switch( mRotationAngle )
376       {
377         case 0:
378         {
379           windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
380           break;
381         }
382         case 90:
383         {
384           windowTransform = WL_OUTPUT_TRANSFORM_90;
385           break;
386         }
387         case 180:
388         {
389           windowTransform = WL_OUTPUT_TRANSFORM_180;
390           break;
391         }
392         case 270:
393         {
394           windowTransform = WL_OUTPUT_TRANSFORM_270;
395           break;
396         }
397         default:
398         {
399           windowTransform = WL_OUTPUT_TRANSFORM_NORMAL;
400           break;
401         }
402       }
403
404       wl_egl_window_set_window_transform( mEglWindow, windowTransform );
405     }
406 #endif
407
408     // Resize case
409     if( !mResizeFinished )
410     {
411       wl_egl_window_resize( mEglWindow, mPositionSize.width, mPositionSize.height, mPositionSize.x, mPositionSize.y );
412       mResizeFinished = true;
413
414       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::PreRender: Set resize\n" );
415     }
416   }
417
418   return true;
419 }
420
421 void WindowRenderSurfaceEcoreWl::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
422 {
423   if( resizingSurface )
424   {
425     if( !mRotationFinished )
426     {
427       DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::PostRender: Trigger rotation event\n" );
428
429       mRotationTrigger->Trigger();
430
431       if( mThreadSynchronization )
432       {
433         // Wait until the event-thread complete the rotation event processing
434         mThreadSynchronization->PostRenderWaitForCompletion();
435       }
436     }
437   }
438
439   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
440   eglImpl.SwapBuffers();
441
442   if( mRenderNotification )
443   {
444     mRenderNotification->Trigger();
445   }
446 }
447
448 void WindowRenderSurfaceEcoreWl::StopRender()
449 {
450 }
451
452 void WindowRenderSurfaceEcoreWl::SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization )
453 {
454   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::SetThreadSynchronization: called\n" );
455
456   mThreadSynchronization = &threadSynchronization;
457 }
458
459 void WindowRenderSurfaceEcoreWl::ReleaseLock()
460 {
461   // Nothing to do.
462 }
463
464 RenderSurface::Type WindowRenderSurfaceEcoreWl::GetSurfaceType()
465 {
466   return RenderSurface::WINDOW_RENDER_SURFACE;
467 }
468
469 void WindowRenderSurfaceEcoreWl::CreateRenderable()
470 {
471    // if width or height are zero, go full screen.
472   if ( (mPositionSize.width == 0) || (mPositionSize.height == 0) )
473   {
474     // Default window size == screen size
475     mPositionSize.x = 0;
476     mPositionSize.y = 0;
477
478     ecore_wl_screen_size_get( &mPositionSize.width, &mPositionSize.height );
479   }
480
481   mWlWindow = ecore_wl_window_new( 0, mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height, ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW );
482
483   if ( mWlWindow == 0 )
484   {
485     DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
486   }
487
488   mWlSurface = ecore_wl_window_surface_create( mWlWindow );
489
490   if( mColorDepth == COLOR_DEPTH_32 )
491   {
492     ecore_wl_window_alpha_set( mWlWindow, true );
493   }
494   else
495   {
496     ecore_wl_window_alpha_set( mWlWindow, false );
497   }
498
499   // Get output transform
500   if( !ecore_wl_window_ignore_output_transform_get( mWlWindow ) )
501   {
502     Ecore_Wl_Output* output = ecore_wl_window_output_find( mWlWindow );
503
504     int transform = ecore_wl_output_transform_get( output );
505
506     mScreenRotationAngle = transform * 90;
507     mScreenRotationFinished = false;
508   }
509 }
510
511 void WindowRenderSurfaceEcoreWl::UseExistingRenderable( unsigned int surfaceId )
512 {
513   mWlWindow = AnyCast< Ecore_Wl_Window* >( surfaceId );
514 }
515
516 unsigned int WindowRenderSurfaceEcoreWl::GetSurfaceId( Any surface ) const
517 {
518   unsigned int surfaceId = 0;
519
520   if( surface.Empty() == false )
521   {
522     // check we have a valid type
523     DALI_ASSERT_ALWAYS( ( (surface.GetType() == typeid (Ecore_Wl_Window *) ) )
524                         && "Surface type is invalid" );
525
526     surfaceId = AnyCast<unsigned int>( surface );
527   }
528   return surfaceId;
529 }
530
531 void WindowRenderSurfaceEcoreWl::ProcessRotationRequest()
532 {
533   mRotationFinished = true;
534
535   ecore_wl_window_rotation_change_done_send( mWlWindow );
536
537   DALI_LOG_INFO( gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurfaceEcoreWl::ProcessRotationRequest: Rotation Done\n" );
538
539   if( mThreadSynchronization )
540   {
541     mThreadSynchronization->PostRenderComplete();
542   }
543 }
544
545 } // namespace Adaptor
546
547 } // namespace internal
548
549 } // namespace Dali