Add pepper-dali
[platform/core/uifw/pepper-dali.git] / pepper-dali / internal / object-impl.cpp
1 /*
2  * Copyright (c) 2016 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 <pepper-dali/internal/object-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <pepper-dali/internal/shell-client-impl.h>
23 #include <pepper-dali/internal/object-view-impl.h>
24
25 // EXTERNAL INCLUDES
26 #include <dali/integration-api/debug.h>
27 #include <dali/public-api/images/buffer-image.h>
28 #include <dali/public-api/events/touch-event.h>
29 #include <dali/public-api/adaptor-framework/native-image-source.h>
30 #include <wayland-tbm-server.h>
31
32 namespace Dali
33 {
34
35 namespace Pepper
36 {
37
38 namespace Internal
39 {
40
41 namespace
42 {
43
44 #if defined(DEBUG_ENABLED)
45 Integration::Log::Filter* gPepperObjectLogging  = Integration::Log::Filter::New( Debug::Verbose, false, "LOG_PEPPER_OBJECT" );
46 #endif
47
48 } // unnamed namespace
49
50 ObjectPtr Object::New( pepper_surface_t* surface, Pepper::Input input )
51 {
52   ObjectPtr impl = new Object();
53
54   // Second-phase init of the implementation
55   impl->Initialize( surface, input );
56
57   return impl;
58 }
59
60 Object::Object()
61 : mSurface( NULL ),
62   mBuffer( NULL ),
63   mPointer( NULL ),
64   mKeyboard( NULL ),
65   mTouch( NULL ),
66   mShmBuffer( NULL ),
67   mTbmSurface( 0 ),
68   mSurfaceDestroyListener( NULL ),
69   mBufferDestroyListener( NULL ),
70   mWidth( 0 ),
71   mHeight( 0 )
72 {
73 }
74
75 Object::~Object()
76 {
77   if( mBuffer )
78   {
79     pepper_buffer_unreference( mBuffer );
80     pepper_event_listener_remove( mBufferDestroyListener );
81   }
82
83   if( mSurfaceDestroyListener )
84   {
85     pepper_event_listener_remove( mSurfaceDestroyListener );
86   }
87 }
88
89 void Object::Initialize( pepper_surface_t* surface, Pepper::Input input )
90 {
91   mSurface = surface;
92
93   mPointer = input.GetPointer();
94   mKeyboard = input.GetKeyboard();
95   mTouch = input.GetTouch();
96
97   mSurfaceDestroyListener = pepper_object_add_event_listener( (pepper_object_t*)surface, PEPPER_EVENT_OBJECT_DESTROY, 0, Object::OnDestroySurface, this );
98
99   DALI_LOG_INFO( gPepperObjectLogging, Debug::Verbose, "Object::Initialize: success\n" );
100 }
101
102 bool Object::AttchBuffer( int* width, int* height )
103 {
104   pepper_buffer_t* buffer;
105   wl_resource* bufferResource;
106   wl_shm_buffer* shmBuffer;
107   tbm_surface_h tbmSurface;
108   int bufWidth, bufHeight;
109
110   buffer = pepper_surface_get_buffer( mSurface );
111   if( !buffer )
112   {
113     DALI_LOG_INFO( gPepperObjectLogging, Debug::General, "Object::AttchBuffer: pepper_surface_get_buffer is failed\n" );
114     return false;
115   }
116
117   if( mBuffer )
118   {
119     pepper_buffer_unreference( mBuffer );
120     pepper_event_listener_remove( mBufferDestroyListener );
121   }
122
123   pepper_buffer_reference( buffer );
124
125   mBuffer = buffer;
126   mBufferDestroyListener = pepper_object_add_event_listener( (pepper_object_t*)buffer, PEPPER_EVENT_OBJECT_DESTROY, 0, Object::OnDestroyBuffer, this );
127
128   bufferResource = pepper_buffer_get_resource( buffer );
129
130   shmBuffer = wl_shm_buffer_get( bufferResource );
131   if( shmBuffer )
132   {
133     bufWidth = wl_shm_buffer_get_width( shmBuffer );
134     bufHeight = wl_shm_buffer_get_height( shmBuffer );
135   }
136   else
137   {
138     tbmSurface = wayland_tbm_server_get_surface( NULL, bufferResource );
139     if( tbmSurface )
140     {
141       bufWidth = tbm_surface_get_width( tbmSurface );
142       bufHeight = tbm_surface_get_height( tbmSurface );
143     }
144     else
145     {
146       DALI_LOG_INFO( gPepperObjectLogging, Debug::General, "Object::AttchBuffer: Failed to get buffer\n" );
147       return false;
148     }
149   }
150
151   if( !mObjectView )
152   {
153     mObjectView = Pepper::ObjectView::New();
154
155     mObjectView.TouchedSignal().Connect( this, &Object::OnTouched );
156
157     // Set surface
158     Pepper::GetImplementation( mObjectView ).SetSurface( mSurface );
159
160     // TODO: support multi touch, focus in/out, mouse in/out
161
162     // TODO: resize callback
163
164     Pepper::Object handle( this );
165     mObjectViewAddedSignal.Emit( handle, mObjectView );
166   }
167
168   if( shmBuffer != mShmBuffer )
169   {
170     // create a new image
171     PixelBuffer* pixelBuffer = static_cast< PixelBuffer* >( wl_shm_buffer_get_data( shmBuffer ) );
172     mBufferImage = BufferImage::New( pixelBuffer, bufWidth, bufHeight );
173
174     mObjectView.SetImage( mBufferImage );
175
176     mShmBuffer = shmBuffer;
177   }
178   else if ( tbmSurface != mTbmSurface )
179   {
180     NativeImageSourcePtr nativeImageSource = NativeImageSource::New( tbmSurface );
181     mNativeImage = NativeImage::New( *nativeImageSource );
182
183     mObjectView.SetImage( mNativeImage );
184
185     mTbmSurface = tbmSurface;
186   }
187
188   if( ( mWidth != bufWidth ) || ( mHeight != bufHeight ) )
189   {
190     mWidth = bufWidth;
191     mHeight = bufHeight;
192
193     // resize actor
194     mObjectView.SetSize( mWidth, mHeight );
195   }
196
197   if( width )
198   {
199     *width = bufWidth;
200   }
201
202   if( height )
203   {
204     *height = bufHeight;
205   }
206
207   DALI_LOG_INFO( gPepperObjectLogging, Debug::Verbose, "Object::AttchBuffer: this = %p, width = %d, height = %d", this, bufWidth, bufHeight );
208
209   return true;
210 }
211
212 Pepper::Object::ObjectSignalType& Object::ObjectViewAddedSignal()
213 {
214   return mObjectViewAddedSignal;
215 }
216
217 Pepper::Object::ObjectSignalType& Object::ObjectViewDeletedSignal()
218 {
219   return mObjectViewDeletedSignal;
220 }
221
222 bool Object::OnTouched( Actor actor, const TouchEvent& touchEvent )
223 {
224   const TouchPoint& point = touchEvent.GetPoint(0);
225
226   Pepper::Internal::ShellClientPtr shellClient = reinterpret_cast< Pepper::Internal::ShellClient* >( pepper_object_get_user_data( reinterpret_cast< pepper_object_t* >( mSurface ), pepper_surface_get_role( mSurface ) ) );
227   if( !shellClient )
228   {
229     DALI_LOG_INFO( gPepperObjectLogging, Debug::General, "Object::OnTouched: shellClient is null. mSurface = %p\n", mSurface );
230     return false;
231   }
232
233   switch( point.state )
234   {
235     case TouchPoint::Down:
236     {
237       pepper_touch_add_point( mTouch, point.deviceId, point.local.x, point.local.y );
238       pepper_touch_send_down( mTouch, shellClient->GetView(), touchEvent.time, point.deviceId, point.local.x, point.local.y );
239
240       DALI_LOG_INFO( gPepperObjectLogging, Debug::Verbose, "Object::OnTouched: Touch Down (%.2f, %.2f) device = %d surface = %p\n", point.local.x, point.local.y, point.deviceId, mSurface );
241       return true;
242     }
243     case TouchPoint::Up:
244     {
245       pepper_touch_send_up( mTouch, shellClient->GetView(), touchEvent.time, point.deviceId );
246       pepper_touch_remove_point( mTouch, point.deviceId );
247
248       DALI_LOG_INFO( gPepperObjectLogging, Debug::Verbose, "Object::OnTouched: Touch Up (%.2f, %.2f) surface = %p\n", point.local.x, point.local.y, mSurface );
249       return true;
250     }
251     case TouchPoint::Motion:
252     {
253       pepper_touch_send_motion( mTouch, shellClient->GetView(), touchEvent.time, point.deviceId, point.local.x, point.local.y );
254
255 //      DALI_LOG_INFO( gPepperObjectLogging, Debug::Verbose, "Object::OnTouched: Touch Motion (%.2f, %.2f)\n", point.local.x, point.local.y );
256       return true;
257     }
258     default:
259     {
260       return false;
261     }
262   }
263
264   return false;
265 }
266
267 void Object::OnDestroySurface( pepper_event_listener_t* listener, pepper_object_t* pepperObject, uint32_t id, void* info, void* data )
268 {
269   Object* object = static_cast< Object* >( data );
270
271   Pepper::Object handle( object );
272   object->mObjectViewDeletedSignal.Emit( handle, object->mObjectView );
273
274   object->mSurface = NULL;
275
276   if( object->mSurfaceDestroyListener )
277   {
278     pepper_event_listener_remove( object->mSurfaceDestroyListener );
279   }
280 }
281
282 void Object::OnDestroyBuffer( pepper_event_listener_t* listener, pepper_object_t* pepperObject, uint32_t id, void* info, void* data )
283 {
284   Object* object = static_cast< Object* >( data );
285
286   if( object->mBuffer )
287   {
288     pepper_buffer_unreference( object->mBuffer );
289     pepper_event_listener_remove( object->mBufferDestroyListener );
290   }
291
292   if( object->mShmBuffer )
293   {
294     void* shmData = wl_shm_buffer_get_data( object->mShmBuffer );
295
296     object->mBufferImage = BufferImage::New( object->mWidth, object->mHeight );
297
298     PixelBuffer* buffer = object->mBufferImage.GetBuffer();
299     memcpy(buffer, shmData, object->mWidth * object->mHeight * 4);
300
301     object->mBufferImage.Update();
302
303     object->mObjectView.SetImage( object->mBufferImage );
304   }
305   else if( object->mTbmSurface )
306   {
307   }
308 }
309
310 } // namespace Internal
311
312 } // namespace Pepper
313
314 } // namespace Dali