2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://floralicense.org/license/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
18 * @file FShell_AppWidgetLayer.cpp
19 * @brief This is the implementation file for the _AppWidgetLayer class.
27 #include <X11/extensions/XShm.h>
28 #include <X11/Xutil.h>
32 #include <provider_buffer.h>
33 #include <FBaseSysLog.h>
34 #include <FBase_StringConverter.h>
35 #include <FGrpRectangle.h>
36 #include "FUi_Window.h"
37 #include "FShell_AppWidgetLayer.h"
38 #include "FShell_AppWidgetProviderManagerImpl.h"
40 //#define _BUFFER_TEST
43 using namespace Tizen::Base;
44 using namespace Tizen::Graphics;
45 using namespace Tizen::Ui::Animations;
46 using namespace Tizen::Ui;
47 using namespace Tizen::Shell;
53 AllocRenderBuffer(void* pData, int size)
55 _AppWidgetLayer* pAppWidgetLayer = static_cast<_AppWidgetLayer*>(pData);
56 SysTryReturn(NID_UI_CTRL, pAppWidgetLayer, null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
58 return pAppWidgetLayer->AllocCanvas(size);
62 FreeRenderBuffer(void* pData, void* pCanvas)
64 SysTryReturnVoidResult(NID_UI_CTRL, pCanvas, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
66 _AppWidgetLayer* pAppWidgetLayer = static_cast<_AppWidgetLayer*>(pData);
67 SysTryReturnVoidResult(NID_UI_CTRL, pAppWidgetLayer, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
69 pAppWidgetLayer->FreeCanvas(pCanvas);
73 PostRender(void* pData, Evas* pEvas, void* pEventInfo)
75 _AppWidgetLayer* pAppWidgetLayer = static_cast<_AppWidgetLayer*>(pData);
76 SysTryReturnVoidResult(NID_UI_CTRL, pAppWidgetLayer, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
78 pAppWidgetLayer->OnRendered();
83 namespace Tizen { namespace Shell
86 _AppWidgetLayer::_AppWidgetLayer(const FloatDimension& size)
92 , __pRenderBuffer(null)
98 _AppWidgetLayer::~_AppWidgetLayer(void)
100 __pRenderBuffer = null;
105 _AppWidgetLayer::OnConstructed(void)
107 result r = E_SUCCESS;
109 unique_ptr<Ecore_Evas, _EcoreEvasDeleter> pEcoreEvas(ecore_evas_buffer_allocfunc_new(__size.width, __size.height, AllocRenderBuffer, FreeRenderBuffer, this));
110 SysTryReturn(NID_UI_CTRL, pEcoreEvas, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
112 ecore_evas_alpha_set(pEcoreEvas.get(), EINA_TRUE);
113 ecore_evas_manual_render_set(pEcoreEvas.get(), EINA_FALSE);
114 ecore_evas_resize(pEcoreEvas.get(), __size.width, __size.height);
115 ecore_evas_activate(pEcoreEvas.get());
117 Evas* pEvas = ecore_evas_get(pEcoreEvas.get());
118 SysTryReturn(NID_UI_CTRL, pEvas, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
120 evas_event_callback_add(pEvas, EVAS_CALLBACK_RENDER_POST, PostRender, this);
122 unique_ptr<Evas_Object, _EvasObjectDeleter> pEvasObject(evas_object_rectangle_add(pEvas));
123 SysTryReturn(NID_UI_CTRL, pEvasObject, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
125 evas_object_resize(pEvasObject.get(), __size.width, __size.height);
126 evas_object_color_set(pEvasObject.get(), 0, 0, 0, 255);
128 r = Initialize(pEvasObject.get());
129 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
131 __pEcoreEvas = move(pEcoreEvas);
132 __pEvasObject = move(pEvasObject);
134 ecore_evas_alpha_set(__pEcoreEvas.get(), EINA_TRUE);
135 evas_object_color_set(__pEvasObject.get(), 0, 0, 0, 0);
141 _AppWidgetLayer::SetProviderId(const String& providerId)
143 __providerId = providerId;
145 __pixmapId = AcquirePixmap();
146 SysTryReturn(NID_UI_CTRL, __pixmapId != -1, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
148 SysLog(NID_UI_CTRL, "pixmapId (%d)", __pixmapId);
150 result r = RegisterTouchEventListener();
151 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
157 _AppWidgetLayer::GetProviderId(void) const
163 _AppWidgetLayer::GetPixmapId(void) const
169 _AppWidgetLayer::SetLayerBounds(const FloatRectangle& bounds)
171 __size = FloatDimension(bounds.width, bounds.height);
173 ecore_evas_resize(__pEcoreEvas.get(), __size.width, __size.height);
175 // FloatRectangle fBounds(static_cast<float>(bounds.x), static_cast<float>(bounds.y), static_cast<float>(bounds.width), static_cast<float>(bounds.height));
180 _AppWidgetLayer::AllocCanvas(int size)
182 SysTryReturn(NID_UI_CTRL, size > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
185 void* pBuffer = malloc(__bufferSize);
186 SysTryReturn(NID_UI_CTRL, pBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
188 __pRenderBuffer = pBuffer;
190 SysLog(NID_UI_CTRL, "buffer (0x%x) size (%d)", pBuffer, __bufferSize);
192 __isReleased = false;
194 return __pRenderBuffer;
198 _AppWidgetLayer::FreeCanvas(void* pCanvas)
212 __pRenderBuffer = null;
216 _AppWidgetLayer::SyncPixmap(const FloatDimension& size)
218 SysTryReturn(NID_UI_CTRL, __pRenderBuffer, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
220 SysLog(NID_UI_CTRL, "buffer (0x%x) size (%d) pixmapId (%d) width(%f) height(%f)", __pRenderBuffer, __bufferSize, __pixmapId, size.width, size.height);
222 Display* pDisplay = static_cast<Display*>(ecore_x_display_get());
223 SysTryReturn(NID_UI_CTRL, pDisplay, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
225 result r = E_SUCCESS;
226 XShmSegmentInfo xShmSegmentInfo;
227 XImage* pXImage = null;
229 Screen* pScreen = null;
230 Visual* pVisual = null;
232 xShmSegmentInfo.shmid = shmget(IPC_PRIVATE, __bufferSize, IPC_CREAT | 0666);
233 SysTryReturn(NID_UI_CTRL, xShmSegmentInfo.shmid >= 0, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
235 xShmSegmentInfo.readOnly = False;
236 xShmSegmentInfo.shmaddr = static_cast<char*>(shmat(xShmSegmentInfo.shmid, null, 0));
237 SysTryCatch(NID_UI_CTRL, xShmSegmentInfo.shmaddr != (void *)-1, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
239 pScreen = DefaultScreenOfDisplay(pDisplay);
240 SysTryCatch(NID_UI_CTRL, pScreen, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
242 pVisual = DefaultVisualOfScreen(pScreen);
243 SysTryCatch(NID_UI_CTRL, pVisual, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
245 pXImage = XShmCreateImage(pDisplay, pVisual, 32, ZPixmap, null, &xShmSegmentInfo, size.width, size.height);
246 SysTryCatch(NID_UI_CTRL, pXImage, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
248 pXImage->data = xShmSegmentInfo.shmaddr;
249 XShmAttach(pDisplay, &xShmSegmentInfo);
250 XSync(pDisplay, False);
252 gc = XCreateGC(pDisplay, static_cast<Pixmap>(__pixmapId), 0, null);
253 SysTryCatch(NID_UI_CTRL, gc, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
255 memcpy(pXImage->data, __pRenderBuffer, __bufferSize);
257 #if defined(_BUFFER_TEST)
259 FILE* pFile = null;
\r
260 static int idx = 0;
\r
261 char filename[1024];
\r
262 snprintf(filename, sizeof(filename), "/opt/out%d.raw", idx++);
\r
263 pFile = fopen(filename, "w+b");
\r
266 fwrite(__pRenderBuffer, __bufferSize, 1, pFile);
\r
268 SysLog(NID_UI_CTRL, "_BUFFER_TEST: buffer (0x%x) size (%d) pixmapId (%d) width(%f) height(%f)", __pRenderBuffer, __bufferSize, __pixmapId, size.width, size.height);
\r
272 SysLog(NID_UI_CTRL, "File open failed: (%s) buffer (0x%x) size (%d) pixmapId (%d)", strerror(errno), __pRenderBuffer, __bufferSize, __pixmapId);
\r
275 #endif // _BUFFER_TEST
277 // Do not send the event. Instead of X event, master will send the updated event to the viewer
278 XShmPutImage(pDisplay, static_cast<Pixmap>(__pixmapId), gc, pXImage, 0, 0, 0, 0, size.width, size.height, False);
279 XSync(pDisplay, False);
281 XFreeGC(pDisplay, gc);
282 XShmDetach(pDisplay, &xShmSegmentInfo);
283 XDestroyImage(pXImage);
285 if (xShmSegmentInfo.shmaddr != (void *)-1)
287 shmdt(xShmSegmentInfo.shmaddr);
290 if (xShmSegmentInfo.shmid >= 0)
292 shmctl(xShmSegmentInfo.shmid, IPC_RMID, 0);
301 XShmDetach(pDisplay, &xShmSegmentInfo);
306 XDestroyImage(pXImage);
309 if (xShmSegmentInfo.shmaddr != (void *)-1)
311 shmdt(xShmSegmentInfo.shmaddr);
314 if (xShmSegmentInfo.shmid >= 0)
316 shmctl(xShmSegmentInfo.shmid, IPC_RMID, 0);
319 return E_OUT_OF_MEMORY;
323 _AppWidgetLayer::OnRendered(void)
325 if (__pixmapId == -1)
327 __pixmapId = AcquirePixmap();
328 SysTryReturnVoidResult(NID_UI_CTRL, __pixmapId >= 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
331 result r = SyncPixmap(__size);
332 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
335 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
339 _AppWidgetLayer::RegisterTouchEventListener(void)
341 result r = _AppWidgetProviderManagerImpl::GetInstance()->SetAppWidgetTouchEventListener(__providerId, *this);
342 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
348 _AppWidgetLayer::AcquirePixmap(void)
350 SysTryReturn(NID_UI_CTRL, !__providerId.IsEmpty(), -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
354 result r = _AppWidgetProviderManagerImpl::GetInstance()->RequestSharedMemoryId(__providerId, __size.width, __size.height, pixmapId);
355 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, -1, r, "[%s] Propagating.", GetErrorMessage(r));
357 SysLog(NID_UI_CTRL, "pixmapId(%d) size(%f %f)", pixmapId, __size.width, __size.height);
363 _AppWidgetLayer::Sync(const FloatDimension& size)
365 SysTryReturn(NID_UI_CTRL, !__providerId.IsEmpty(), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
367 result r = _AppWidgetProviderManagerImpl::GetInstance()->RequestSyncSharedMemory(__providerId, size.width, size.height);
368 SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
374 _AppWidgetLayer::ReleasePixmap(void)
376 SysTryReturnVoidResult(NID_UI_CTRL, !__providerId.IsEmpty(), E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
378 _AppWidgetProviderManagerImpl::GetInstance()->RequestReleaseSharedMemory(__providerId);
382 _AppWidgetLayer::OnTouchEventRecevied(int eventType, double timestamp, double x, double y)
384 SysLog(NID_UI_CTRL, "eventType (%d) timestamp (%f) (%f, %f)", eventType, timestamp, x, y);
386 int xPos = __size.width * x;
387 int yPos = __size.height * y;
389 Evas* pEvas = ecore_evas_get(__pEcoreEvas.get());
390 SysTryReturn(NID_UI_CTRL, pEvas, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
394 case BUFFER_EVENT_ENTER:
395 evas_event_feed_mouse_in(pEvas, timestamp, null);
398 case BUFFER_EVENT_LEAVE:
399 evas_event_feed_mouse_out(pEvas, timestamp, null);
402 case BUFFER_EVENT_DOWN:
403 evas_event_feed_mouse_in(pEvas, timestamp, null);
404 evas_event_feed_mouse_move(pEvas, xPos, yPos, timestamp + 0.01f, null);
405 evas_event_feed_mouse_down(pEvas, 1, EVAS_BUTTON_NONE, timestamp + 0.02f, null);
408 case BUFFER_EVENT_MOVE:
409 evas_event_feed_mouse_move(pEvas, xPos, yPos, timestamp, null);
412 case BUFFER_EVENT_UP:
413 evas_event_feed_mouse_up(pEvas, 1, EVAS_BUTTON_NONE, timestamp, null);
414 evas_event_feed_mouse_out(pEvas, timestamp + 0.01f, null);