+/* WM_ROTATE */
+static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data)
+{
+ if (cb == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((priv.wm_rot_supported) && (0 == priv.rot_started)) {
+ __set_wm_rotation_support(0, 1);
+ }
+
+ priv.rot_cb = cb;
+ priv.rot_cb_data = data;
+ priv.rot_started = 1;
+
+ return 0;
+}
+
+static int __wm_unset_rotation_cb(void)
+{
+ if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
+ __set_wm_rotation_support(0, 0);
+ }
+
+ priv.rot_cb = NULL;
+ priv.rot_cb_data = NULL;
+ priv.rot_started = 0;
+
+ return 0;
+}
+
+static int __wm_get_rotation_state(enum appcore_rm *curr)
+{
+ if (curr == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *curr = priv.rot_mode;
+
+ return 0;
+}
+
+static int __wm_pause_rotation_cb(void)
+{
+ if ((1 == priv.rot_started) && (priv.wm_rot_supported)) {
+ __set_wm_rotation_support(0, 0);
+ }
+
+ priv.rot_started = 0;
+
+ return 0;
+}
+
+static int __wm_resume_rotation_cb(void)
+{
+ if ((0 == priv.rot_started) && (priv.wm_rot_supported)) {
+ __set_wm_rotation_support(0, 1);
+ }
+
+ priv.rot_started = 1;
+
+ return 0;
+}
+
+static struct ui_wm_rotate wm_rotate = {
+ __wm_set_rotation_cb,
+ __wm_unset_rotation_cb,
+ __wm_get_rotation_state,
+ __wm_pause_rotation_cb,
+ __wm_resume_rotation_cb
+};
+
+#ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
+static Window _get_parent_window(Window id)
+{
+ Window root;
+ Window parent;
+ Window *children;
+ unsigned int num;
+
+ if (!XQueryTree(ecore_x_display_get(), id, &root, &parent, &children, &num)) {
+ return 0;
+ }
+
+ if (children) {
+ XFree(children);
+ }
+
+ return parent;
+}
+
+static Window _find_capture_window(Window id, Visual **visual, int *depth, int *width, int *height)
+{
+ XWindowAttributes attr;
+ Window parent = id;
+ Window orig_id = id;
+
+ if (id == 0) {
+ return (Window)-1;
+ }
+
+ do {
+ id = parent;
+
+ if (!XGetWindowAttributes(ecore_x_display_get(), id, &attr)) {
+ return (Window)-1;
+ }
+
+ parent = _get_parent_window(id);
+
+ if (attr.map_state == IsViewable
+ && attr.override_redirect == True
+ && attr.class == InputOutput && parent == attr.root) {
+ *depth = attr.depth;
+ *width = attr.width;
+ *height = attr.height;
+ *visual = attr.visual;
+ return id;
+ }
+ } while (parent != attr.root && parent != 0);
+
+ XGetWindowAttributes(ecore_x_display_get(), orig_id, &attr);
+ *depth = attr.depth;
+ *width = attr.width;
+ *height = attr.height;
+ *visual = attr.visual;
+
+ return (Window) 0;
+
+}
+
+static char *_capture_window(Window id, Visual *visual, int width, int height, int depth, int *size)
+{
+ XShmSegmentInfo si;
+ XImage *xim;
+ int img_size;
+ char *captured_img = NULL;
+
+ /* (depth >> 3) + 1 == 4 byte */
+ si.shmid =
+ shmget(IPC_PRIVATE, width * height * ((depth >> 3) + 1),
+ IPC_CREAT | 0666);
+
+ if (si.shmid < 0) {
+ _ERR("shmget");
+ return NULL;
+ }
+
+ si.readOnly = False;
+ si.shmaddr = shmat(si.shmid, NULL, 0);
+
+ if (si.shmaddr == (char *)-1) {
+ shmdt(si.shmaddr);
+ shmctl(si.shmid, IPC_RMID, 0);
+ return NULL;
+ }
+
+ xim = XShmCreateImage(ecore_x_display_get(), visual, depth, ZPixmap, NULL, &si,
+ width, height);
+
+ if (xim == 0) {
+ shmdt(si.shmaddr);
+ shmctl(si.shmid, IPC_RMID, 0);
+
+ return NULL;
+ }
+
+ img_size = xim->bytes_per_line * xim->height;
+ xim->data = si.shmaddr;
+
+ XSync(ecore_x_display_get(), False);
+ XShmAttach(ecore_x_display_get(), &si);
+ XShmGetImage(ecore_x_display_get(), id, xim, 0, 0, 0xFFFFFFFF);
+ XSync(ecore_x_display_get(), False);
+
+ captured_img = calloc(1, img_size);
+ if (captured_img) {
+ memcpy(captured_img, xim->data, img_size);
+ } else {
+ _ERR("calloc");
+ }
+
+ XShmDetach(ecore_x_display_get(), &si);
+ XDestroyImage(xim);
+
+
+ shmdt(si.shmaddr);
+ shmctl(si.shmid, IPC_RMID, 0);
+
+ *size = img_size;
+
+ return captured_img;
+
+}
+
+#define _WND_REQUEST_ANGLE_IDX 0
+#define _WND_CURR_ANGLE_IDX 1
+int _get_angle(Ecore_X_Window win)
+{
+ int after = -1;
+ int before = -1;
+
+ do {
+ int ret, count;
+ int angle[2] = {-1, -1};
+ unsigned char* prop_data = NULL;
+
+ ret = ecore_x_window_prop_property_get(win,
+ ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
+ ECORE_X_ATOM_CARDINAL,
+ 32,
+ &prop_data,
+ &count);
+ if (ret <= 0) {
+ if (prop_data) free(prop_data);
+ break;
+ }
+
+ if (prop_data) {
+ memcpy(&angle, prop_data, sizeof (int) *count);
+ free(prop_data);
+ }
+
+ after= angle[_WND_REQUEST_ANGLE_IDX];
+ before = angle[_WND_CURR_ANGLE_IDX];
+ } while (0);
+
+ if (-1 == after) after = 0;
+
+ return after;
+}
+
+static void _rotate_img(Evas_Object *image_object, int angle, int cx, int cy)
+{
+ Evas_Map *em;
+
+ _ret_if(NULL == image_object);
+
+ em = evas_map_new(4);
+ _ret_if(NULL == em);
+
+ evas_map_util_points_populate_from_object(em, image_object);
+ evas_map_util_rotate(em, (double) angle, cx, cy);
+
+ evas_object_map_set(image_object, em);
+ evas_object_map_enable_set(image_object, EINA_TRUE);
+
+ evas_map_free(em);
+}
+
+#define EXTENSION_LEN 128
+#define CAPTURE_FILE_PATH "/opt/usr/share/app_capture"
+bool _make_capture_file(const char *package, int width, int height, char *img, int angle)
+{
+ int len;
+ char *filename;
+ Evas *e;
+ Evas_Object *image_object;
+ int canvas_width, canvas_height;
+ int cx = 0, cy = 0;
+ int mx = 0;
+ int r = 0;
+
+ _retv_if(NULL == package, false);
+
+ len = strlen(package) + EXTENSION_LEN;
+ filename = malloc(len);
+ _retv_if(NULL == filename, false);
+ snprintf(filename, len, CAPTURE_FILE_PATH"/%s.jpg", package);
+
+ if (90 == angle || 270 == angle) {
+ canvas_width = height;
+ canvas_height = width;
+ } else {
+ canvas_width = width;
+ canvas_height = height;
+ }
+
+ e = virtual_canvas_create(canvas_width, canvas_height);
+ goto_if(NULL == e, error);
+
+ image_object = evas_object_image_add(e);
+ goto_if(NULL == image_object, error);
+
+ evas_object_image_size_set(image_object, width, height);
+ evas_object_image_data_set(image_object, img);
+ evas_object_image_data_update_add(image_object, 0, 0, width, height);
+ evas_object_resize(image_object, width, height);
+ evas_object_image_filled_set(image_object, EINA_TRUE);
+ switch (angle) {
+ case 90:
+ cx = canvas_width - width / 2;
+ cy = canvas_height / 2;
+ mx = canvas_width - width;
+ break;
+ case 180:
+ cx = width / 2;
+ cy = height / 2;
+ break;
+ case 270:
+ cx = width / 2;
+ cy = canvas_height / 2;
+ break;
+ default:
+ break;
+ }
+ evas_object_move(image_object, mx, 0);
+ _rotate_img(image_object, angle, cx, cy);
+ evas_object_show(image_object);
+
+ if (access(CAPTURE_FILE_PATH, F_OK) != 0) {
+ r = mkdir(CAPTURE_FILE_PATH, 0777);
+ goto_if(r < 0, error);
+ }
+ goto_if(false == virtual_canvas_flush_to_file(e, filename, canvas_width, canvas_height), error);
+
+ evas_object_del(image_object);
+ virtual_canvas_destroy(e);
+ free(filename);
+
+ return true;
+
+error:
+ do {
+ free(filename);
+
+ if (!e) break;
+ virtual_canvas_destroy(e);
+
+ if (!image_object) break;
+ evas_object_del(image_object);
+ } while (0);
+
+ return false;
+}
+
+int __resize8888(const char* pDataIn, char* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
+{
+ int scaleX = 0;
+ int scaleY = 0;
+ int i = 0;
+ int j = 0;
+ int iRow = 0;
+ int iIndex = 0;
+ char* pOutput = pDataOut;
+ char* pOut = pDataOut;
+ const char* pIn = NULL;
+ int *pColLUT = malloc(sizeof(int) * outWidth);
+
+ /* Calculate X Scale factor */
+ scaleX = inWidth * 256 / outWidth;
+ /* Calculate Y Scale factor, aspect ratio is not maintained */
+ scaleY = inHeight * 256 / outHeight;
+ for (j = 0; j < outWidth; j++)
+ {
+ /* Get input index based on column scale factor */
+ /* To get more optimization, this is calculated once and
+ * is placed in a LUT and used for indexing
+ */
+ pColLUT [j] = ((j * scaleX) >> 8) * 4;
+ }
+ pOut = pOutput;
+ for (i = 0; i < outHeight; i++)
+ {
+ /* Get input routWidth index based on routWidth scale factor */
+ iRow = (i * scaleY >> 8) * inWidth * 4;
+ /* Loop could be unrolled for more optimization */
+ for (j = 0; j < (outWidth); j++)
+ {
+ /* Get input index based on column scale factor */
+ iIndex = iRow + pColLUT [j];
+ pIn = pDataIn + iIndex;
+ *pOut++ = *pIn++;
+ *pOut++ = *pIn++;
+ *pOut++ = *pIn++;
+ *pOut++ = *pIn++;
+ }
+ }
+
+ free(pColLUT);
+ return 0;
+}
+
+static void _capture_and_make_file(Ecore_X_Window win, int pid, const char *package)
+{
+ Visual *visual;
+ Window redirected_id;
+
+ int width, height, depth;
+ int width_out, height_out;
+ int size = 0;
+ int angle;
+
+ char *img;
+
+ redirected_id = _find_capture_window(win, &visual, &depth, &width, &height);
+ _ret_if(redirected_id == (Window) -1 ||
+ redirected_id == (Window) 0);
+
+ SECURE_LOGD("Capture : win[%x] -> redirected win[%x] for %s[%d]", win, redirected_id, package, pid);
+
+ img = _capture_window(redirected_id, visual, width, height, depth, &size);
+ _ret_if(NULL == img);
+
+ width_out = width/2;
+ height_out = height/2;
+
+ if ( width_out < 1 || height_out < 1 ) {
+ free(img);
+ return;
+ }
+
+ __resize8888(img, img, width, height, width_out, height_out);
+
+ angle = _get_angle(win);
+ if (false == _make_capture_file(package, width_out, height_out, img, angle)) {
+ _ERR("cannot a capture file for the package of [%s]", package);
+ }
+
+ free(img);
+}
+#endif
+
+extern int aul_status_update(int status);
+