2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file web_app_core_tskmgr_util.cpp
18 * @author Prathmesh Manurkar (prathmesh.m@samsung.com)
21 #include "web_app_core_tskmgr_util.h"
25 #include <dpl/log/wrt_log.h>
26 #include <Ecore_Evas.h>
28 #include <Elementary.h>
29 #include <X11/extensions/Xcomposite.h>
30 #include <X11/extensions/XShm.h>
31 #include <X11/Xatom.h>
33 #include <X11/Xutil.h>
35 #define QUALITY_N_COMPRESS "quality=100 compress=1"
37 static Evas *createVirtualCanvas(int w, int h)
39 Ecore_Evas *internal_ee;
42 // Create virtual canvas
43 internal_ee = ecore_evas_buffer_new(w, h);
45 WrtLogW("Failed to create a new canvas buffer");
49 ecore_evas_alpha_set(internal_ee, EINA_TRUE);
50 ecore_evas_manual_render_set(internal_ee, EINA_TRUE);
52 // Get the "Evas" object from a virtual canvas
53 internal_e = ecore_evas_get(internal_ee);
55 ecore_evas_free(internal_ee);
56 WrtLogW("Faield to get Evas object");
65 static bool flushDataToFile(Evas *e, void *data, const char *filename, int w, int h)
69 output = evas_object_image_add(e);
71 WrtLogW("Failed to create an image object");
75 evas_object_image_data_set(output, NULL);
76 evas_object_image_colorspace_set(output, EVAS_COLORSPACE_ARGB8888);
77 evas_object_image_alpha_set(output, EINA_TRUE);
78 evas_object_image_size_set(output, w, h);
79 evas_object_image_smooth_scale_set(output, EINA_TRUE);
80 evas_object_image_data_set(output, data);
81 evas_object_image_data_update_add(output, 0, 0, w, h);
83 if (evas_object_image_save(output, filename, NULL, QUALITY_N_COMPRESS) == EINA_FALSE) {
84 evas_object_del(output);
85 WrtLogW("Faild to save a captured image (%s)", filename);
89 evas_object_del(output);
91 if (access(filename, F_OK) != 0) {
92 WrtLogW("File %s is not found", filename);
101 static bool flushVirtualCanvasToFile(Evas *e, const char *filename, int w, int h)
104 Ecore_Evas *internal_ee;
106 internal_ee = ecore_evas_ecore_evas_get(e);
108 WrtLogW("Failed to get ecore evas");
112 ecore_evas_manual_render(internal_ee);
114 // Get a pointer of a buffer of the virtual canvas
115 data = (void *) ecore_evas_buffer_pixels_get(internal_ee);
117 WrtLogW("Failed to get pixel data");
121 return flushDataToFile(e, data, filename, w, h);
126 static bool destroyVirtualCanvas(Evas *e)
130 ee = ecore_evas_ecore_evas_get(e);
132 WrtLogW("Failed to ecore evas object");
140 static Window getParentWindow(Window id)
147 if (!XQueryTree((Display*)ecore_x_display_get(), id, &root, &parent, &children, &num)) {
158 static Window findCaptureWindow(Window id, Visual **visual, int *depth, int *width, int *height)
160 XWindowAttributes attr;
171 if (!XGetWindowAttributes((Display*)ecore_x_display_get(), id, &attr)) {
175 parent = getParentWindow(id);
177 if (attr.map_state == IsViewable
178 && attr.override_redirect == true
179 && attr.c_class == InputOutput && parent == attr.root) {
182 *height = attr.height;
183 *visual = attr.visual;
186 } while (parent != attr.root && parent != 0);
188 XGetWindowAttributes((Display*)ecore_x_display_get(), orig_id, &attr);
191 *height = attr.height;
192 *visual = attr.visual;
198 static char *captureWindow(Window id, Visual *visual, int width, int height, int depth, int *size)
203 char *captured_img = NULL;
205 /* (depth >> 3) + 1 == 4 byte */
207 shmget(IPC_PRIVATE, width * height * ((depth >> 3) + 1),
216 si.shmaddr = (char*)shmat(si.shmid, NULL, 0);
218 if (si.shmaddr == (char *)-1) {
220 shmctl(si.shmid, IPC_RMID, 0);
224 xim = XShmCreateImage((Display*)ecore_x_display_get(), visual, depth, ZPixmap, NULL, &si,
229 shmctl(si.shmid, IPC_RMID, 0);
234 img_size = xim->bytes_per_line * xim->height;
235 xim->data = si.shmaddr;
237 XSync((Display*)ecore_x_display_get(), False);
238 XShmAttach((Display*)ecore_x_display_get(), &si);
239 XShmGetImage((Display*)ecore_x_display_get(), id, xim, 0, 0, 0xFFFFFFFF);
240 XSync((Display*)ecore_x_display_get(), False);
242 captured_img = (char*)calloc(1, img_size);
244 memcpy(captured_img, xim->data, img_size);
249 XShmDetach((Display*)ecore_x_display_get(), &si);
254 shmctl(si.shmid, IPC_RMID, 0);
261 #define _WND_REQUEST_ANGLE_IDX 0
262 int getAngle(Ecore_X_Window win)
264 WrtLogD("getAngle called");
270 int angle[2] = {-1, -1};
271 unsigned char* prop_data = NULL;
273 ret = ecore_x_window_prop_property_get(win,
274 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
275 ECORE_X_ATOM_CARDINAL,
280 if (prop_data) free(prop_data);
285 memcpy(&angle, prop_data, sizeof (int) *count);
289 after = angle[_WND_REQUEST_ANGLE_IDX];
292 if (-1 == after) after = 0;
297 static void rotateImg(Evas_Object *image_object, int angle, int cx, int cy)
301 if (NULL == image_object)
304 em = evas_map_new(4);
308 evas_map_util_points_populate_from_object(em, image_object);
309 evas_map_util_rotate(em, (double) angle, cx, cy);
311 evas_object_map_set(image_object, em);
312 evas_object_map_enable_set(image_object, EINA_TRUE);
317 #define EXTENSION_LEN 128
318 #define CAPTURE_FILE_PATH "/opt/usr/share/app_capture"
319 static bool makeCaptureFile(const char *package, int width, int height, char *img, int angle)
324 Evas_Object *image_object;
325 int canvas_width, canvas_height;
332 len = strlen(package) + EXTENSION_LEN;
333 filename = (char*)malloc(len);
337 snprintf(filename, len, CAPTURE_FILE_PATH"/%s.jpg", package);
339 if (90 == angle || 270 == angle) {
340 canvas_width = height;
341 canvas_height = width;
343 canvas_width = width;
344 canvas_height = height;
347 e = createVirtualCanvas(canvas_width, canvas_height);
351 image_object = evas_object_image_add(e);
352 if (NULL == image_object)
355 evas_object_image_size_set(image_object, width, height);
356 evas_object_image_data_set(image_object, img);
357 evas_object_image_data_update_add(image_object, 0, 0, width, height);
358 evas_object_resize(image_object, width, height);
359 evas_object_image_filled_set(image_object, EINA_TRUE);
362 cx = canvas_width - width / 2;
363 cy = canvas_height / 2;
364 mx = canvas_width - width;
372 cy = canvas_height / 2;
377 evas_object_move(image_object, mx, 0);
378 rotateImg(image_object, angle, cx, cy);
379 evas_object_show(image_object);
381 if (access(CAPTURE_FILE_PATH, F_OK) != 0) {
382 mkdir(CAPTURE_FILE_PATH, 0777);
384 if(false == flushVirtualCanvasToFile(e, filename, canvas_width, canvas_height))
387 evas_object_del(image_object);
388 destroyVirtualCanvas(e);
398 destroyVirtualCanvas(e);
400 if (!image_object) break;
401 evas_object_del(image_object);
407 static int resizeTo8888(const char* pDataIn, char* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
415 char* pOutput = pDataOut;
416 char* pOut = pDataOut;
417 const char* pIn = NULL;
418 int *pColLUT = (int*)malloc(sizeof(int) * outWidth);
420 /* Calculate X Scale factor */
421 scaleX = inWidth * 256 / outWidth;
422 /* Calculate Y Scale factor, aspect ratio is not maintained */
423 scaleY = inHeight * 256 / outHeight;
424 for (j = 0; j < outWidth; j++) {
425 /* Get input index based on column scale factor */
426 /* To get more optimization, this is calculated once and
427 * is placed in a LUT and used for indexing
429 pColLUT [j] = ((j * scaleX) >> 8) * 4;
432 for (i = 0; i < outHeight; i++) {
433 /* Get input routWidth index based on routWidth scale factor */
434 iRow = (i * scaleY >> 8) * inWidth * 4;
435 /* Loop could be unrolled for more optimization */
436 for (j = 0; j < (outWidth); j++) {
437 /* Get input index based on column scale factor */
438 iIndex = iRow + pColLUT [j];
439 pIn = pDataIn + iIndex;
451 void captureAndMakeFileForTaskMgr(Ecore_X_Window win, const char *package)
454 Window redirected_id;
456 int width, height, depth;
457 int width_out, height_out;
463 redirected_id = findCaptureWindow(win, &visual, &depth, &width, &height);
464 if (redirected_id == (Window) -1 || redirected_id == (Window) 0) {
468 WrtLogD("Capture : win[%x] -> redirected win[%x] for %s", win, redirected_id, package);
470 img = captureWindow(redirected_id, visual, width, height, depth, &size);
476 height_out = height/2;
478 if ( width_out < 1 || height_out < 1 ) {
483 resizeTo8888(img, img, width, height, width_out, height_out);
485 angle = getAngle(win);
486 if (false == makeCaptureFile(package, width_out, height_out, img, angle)) {
487 WrtLogW("cannot a capture file for the package of [%s]", package);