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