Revert "[Tizen] Revert "Support screen rotation""
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / window-render-surface-x.cpp
1 /*
2  * Copyright (c) 2017 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-render-surface.h"
20
21 // EXTERNAL INCLUDES
22 #include <X11/Xatom.h>
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25
26 #include <X11/extensions/Xfixes.h> // for damage notify
27 #include <X11/extensions/Xdamage.h> // for damage notify
28
29 #include <dali/integration-api/gl-abstraction.h>
30 #include <dali/integration-api/debug.h>
31
32 // INTERNAL INCLUDES
33
34 #include <ecore-x-types.h>
35 #include <trigger-event.h>
36 #include <gl/egl-implementation.h>
37 #include <base/display-connection.h>
38
39 namespace Dali
40 {
41
42 #if defined(DEBUG_ENABLED)
43 extern Debug::Filter* gRenderSurfaceLogFilter;
44 #endif
45
46 namespace ECore
47 {
48
49 namespace
50 {
51
52 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
53
54 } // unnamed namespace
55
56 WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
57                                           Any surface,
58                                           const std::string& name,
59                                           const std::string& className,
60                                           bool isTransparent)
61 : EcoreXRenderSurface( positionSize, surface, name, isTransparent ),
62   mX11Window( 0 ),
63   mNeedToApproveDeiconify(false),
64   mClassName(className)
65 {
66   DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n" );
67   Init( surface );
68 }
69
70 WindowRenderSurface::~WindowRenderSurface()
71 {
72   if( mOwnSurface )
73   {
74     ecore_x_window_free( mX11Window );
75   }
76 }
77
78 Ecore_X_Drawable WindowRenderSurface::GetDrawable()
79 {
80   // already an e-core type
81   return static_cast< Ecore_X_Drawable >( mX11Window );
82 }
83
84 Any WindowRenderSurface::GetSurface()
85 {
86   // already an e-core type
87   return Any( mX11Window );
88 }
89
90 Ecore_X_Window WindowRenderSurface::GetXWindow()
91 {
92   return mX11Window;
93 }
94
95 void WindowRenderSurface::RequestToApproveDeiconify()
96 {
97   mNeedToApproveDeiconify = true;
98 }
99
100 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
101 {
102   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
103
104   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
105
106   eglImpl.ChooseConfig(true, mColorDepth);
107 }
108
109 void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
110 {
111   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
112
113   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
114
115   // create the EGL surface
116   // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
117   XWindow window( mX11Window );
118   eglImpl.CreateSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( window ), mColorDepth );
119 }
120
121 void WindowRenderSurface::DestroyEglSurface( EglInterface& eglIf )
122 {
123   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
124
125   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( eglIf );
126   eglImpl.DestroySurface();
127 }
128
129 bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
130 {
131   DALI_LOG_TRACE_METHOD( gRenderSurfaceLogFilter );
132
133   // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
134   XWindow window( mX11Window );
135   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
136
137   return eglImpl.ReplaceSurfaceWindow( reinterpret_cast< EGLNativeWindowType >( window ) );
138 }
139
140 void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
141 {
142   bool needToMove = false;
143   bool needToResize = false;
144
145   // check moving
146   if( (fabs(positionSize.x - mPosition.x) > MINIMUM_DIMENSION_CHANGE) ||
147       (fabs(positionSize.y - mPosition.y) > MINIMUM_DIMENSION_CHANGE) )
148   {
149     needToMove = true;
150   }
151
152   // check resizing
153   if( (fabs(positionSize.width - mPosition.width) > MINIMUM_DIMENSION_CHANGE) ||
154       (fabs(positionSize.height - mPosition.height) > MINIMUM_DIMENSION_CHANGE) )
155   {
156     needToResize = true;
157   }
158
159   if( needToMove &&  needToResize)
160   {
161     ecore_x_window_move_resize(mX11Window, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
162     mPosition = positionSize;
163   }
164   else if(needToMove)
165   {
166     ecore_x_window_move(mX11Window, positionSize.x, positionSize.y);
167     mPosition = positionSize;
168   }
169   else if (needToResize)
170   {
171     ecore_x_window_resize(mX11Window, positionSize.width, positionSize.height);
172     mPosition = positionSize;
173   }
174
175 }
176
177 void WindowRenderSurface::Map()
178 {
179   ecore_x_window_show(mX11Window);
180 }
181
182 void WindowRenderSurface::StartRender()
183 {
184 }
185
186 bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&, bool )
187 {
188   // nothing to do for windows
189   return true;
190 }
191
192 void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface, bool resizingSurface )
193 {
194   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
195   eglImpl.SwapBuffers();
196
197   // When the window is deiconified, it approves the deiconify operation to window manager after rendering
198   if(mNeedToApproveDeiconify)
199   {
200     // SwapBuffer is desychronized. So make sure to sychronize when window is deiconified.
201     glAbstraction.Finish();
202
203     XDisplay* display = AnyCast<XDisplay *>(displayConnection->GetDisplay());
204
205 #ifndef DALI_PROFILE_UBUNTU
206     /* client sends immediately reply message using value 1 */
207     XEvent xev;
208
209     xev.xclient.window = mX11Window;
210     xev.xclient.type = ClientMessage;
211     xev.xclient.message_type = ECORE_X_ATOM_E_DEICONIFY_APPROVE;
212     xev.xclient.format = 32;
213     xev.xclient.data.l[0] = mX11Window;
214     xev.xclient.data.l[1] = 1;
215     xev.xclient.data.l[2] = 0;
216     xev.xclient.data.l[3] = 0;
217     xev.xclient.data.l[4] = 0;
218
219     XSendEvent(display, mX11Window, false, ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, &xev);
220 #endif // DALI_PROFILE_UBUNTU
221
222     XSync(display, false);
223
224     mNeedToApproveDeiconify = false;
225   }
226 }
227
228 void WindowRenderSurface::StopRender()
229 {
230 }
231
232 void WindowRenderSurface::SetViewMode( ViewMode viewMode )
233 {
234   Ecore_X_Atom viewModeAtom( ecore_x_atom_get( "_E_COMP_3D_APP_WIN" ) );
235
236   if( viewModeAtom != None )
237   {
238     unsigned int value( static_cast<unsigned int>( viewMode ) );
239     ecore_x_window_prop_card32_set( mX11Window, viewModeAtom, &value, 1 );
240   }
241 }
242
243 void WindowRenderSurface::CreateXRenderable()
244 {
245    // if width or height are zero, go full screen.
246   if ( (mPosition.width == 0) || (mPosition.height == 0) )
247   {
248     // Default window size == screen size
249     mPosition.x = 0;
250     mPosition.y = 0;
251
252     ecore_x_screen_size_get( ecore_x_default_screen_get(), &mPosition.width, &mPosition.height );
253   }
254
255   if(mColorDepth == COLOR_DEPTH_32)
256   {
257     // create 32 bit window
258     mX11Window = ecore_x_window_argb_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
259   }
260   else
261   {
262     // create 24 bit window
263     mX11Window = ecore_x_window_new( 0, mPosition.x, mPosition.y, mPosition.width, mPosition.height );
264   }
265
266   if ( mX11Window == 0 )
267   {
268       DALI_ASSERT_ALWAYS(0 && "Failed to create X window");
269   }
270
271   // set up window title which will be helpful for debug utitilty
272   ecore_x_icccm_title_set( mX11Window, mTitle.c_str() );
273   ecore_x_netwm_name_set( mX11Window, mTitle.c_str() );
274   ecore_x_icccm_name_class_set( mX11Window, mTitle.c_str(), mClassName.c_str() );
275
276   // set up etc properties to match with ecore-evas
277   char *id = NULL;
278   if( ( id = getenv("DESKTOP_STARTUP_ID") ) )
279   {
280     ecore_x_netwm_startup_id_set( mX11Window, id );
281   }
282
283   ecore_x_icccm_hints_set( mX11Window,
284                            1,                                // accepts_focus
285                            ECORE_X_WINDOW_STATE_HINT_NORMAL, // initial_state
286                            0,                                // icon_pixmap
287                            0,                                // icon_mask
288                            0,                                // icon_window
289                            0,                                // window_group
290                            0 );                              // is_urgent
291
292   // we SHOULD guarantee the x11 window was created in x server.
293   ecore_x_sync();
294 }
295
296 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
297 {
298   mX11Window = static_cast< Ecore_X_Window >( surfaceId );
299 }
300
301 void WindowRenderSurface::SetThreadSynchronization( ThreadSynchronizationInterface& /* threadSynchronization */ )
302 {
303   // Nothing to do.
304 }
305
306 void WindowRenderSurface::ReleaseLock()
307 {
308   // Nothing to do.
309 }
310
311 } // namespace ECore
312
313 } // namespace Dali