Timer in ScreenshotActivity 54/154154/7
authorPawel Kurowski <p.kurowski2@samsung.com>
Sun, 8 Oct 2017 13:51:30 +0000 (15:51 +0200)
committerPawel Kurowski <p.kurowski2@samsung.com>
Mon, 16 Oct 2017 14:21:42 +0000 (16:21 +0200)
According to enlightenment documentation evas_object_del
"marks the given Evas object obj for deletion (when Evas will free its memory). Objects are not freed immediately"
Without additional delay for render cycles, screenshot could capture context menu.

ScreenshotActivity now uses Unique_ptr to handle memory.

Change-Id: Ib703d178fb2c71e4de7a6485fd87d184039a1b1c

src/ScreenshotActivity.cpp

index 7224179..0bcc063 100644 (file)
@@ -4,6 +4,7 @@
 #include "UniversalSwitch.hpp"
 #include "Singleton.hpp"
 #include "Window.hpp"
+#include "ecore.hpp"
 
 #include <efl_util.h>
 #include <cairo.h>
 class ScreenshotActivity : public UIActivity, private RegisterActivity<ScreenshotActivity>
 {
 public:
+       ScreenshotActivity();
+       bool process() override;
+
        constexpr static const char *activityType = "SCREENSHOT";
-       ScreenshotActivity()
-               : UIActivity(activityType), screenshotHandle(nullptr), tbmSurface(nullptr), surface(nullptr),
-                 size(Singleton<UniversalSwitch>::instance().getMainWindow()->getDimensions().size)
-       {}
 
-       ~ScreenshotActivity()
-       {
-               if (surface)
-                       cairo_surface_destroy(surface);
+private:
+       static void capture(const std::string &, Size);
+       static std::string generateFileName();
 
-               if (tbmSurface)
-                       tbm_surface_destroy(tbmSurface);
+       ecore::Timer timer;
+       static constexpr double DELAY = 0.5;
+};
 
-               if (screenshotHandle)
-                       efl_util_screenshot_deinitialize(screenshotHandle);
-       }
+ScreenshotActivity::ScreenshotActivity() : UIActivity(activityType) {}
 
-       bool process() override
-       {
-               char *path = nullptr;
-               if (storage_get_directory(STORAGE_TYPE_INTERNAL, STORAGE_DIRECTORY_IMAGES, &path))
-                       ERROR("storage_get_directory failed");
-
-               if (path) {
-                       filename = path + ("/" + generateFileName());
-                       free(path);
-                       capture();
-               }
+bool ScreenshotActivity::process()
+{
+       char *path = nullptr;
+       storage_get_directory(STORAGE_TYPE_INTERNAL, STORAGE_DIRECTORY_IMAGES, &path);
+       auto directory = std::string {path};
+       free(path);
+
+       if (directory.empty()) {
+               ERROR("No storage path");
                return true;
        }
 
-private:
-       void capture()
-       {
-               screenshotHandle = efl_util_screenshot_initialize(size.width, size.height);
-               if (!screenshotHandle) {
-                       ERROR("Screenshot initialization failed");
-                       return;
-               }
-
-               tbmSurface = efl_util_screenshot_take_tbm_surface(screenshotHandle);
-               if (!tbmSurface) {
-                       ERROR("Taking surface failed");
-                       return;
-               }
-
-               tbm_surface_info_s surfaceInfo;
-               auto error = tbm_surface_get_info(tbmSurface, &surfaceInfo);
-               if (error != TBM_SURFACE_ERROR_NONE) {
-                       ERROR("Get surface info failed");
-                       return;
-               }
-
-               if (surfaceInfo.num_planes < 1) {
-                       ERROR("No planes in surface");
-                       return;
-               }
-
-               auto &plane = surfaceInfo.planes[0];
-               surface = cairo_image_surface_create_for_data(plane.ptr, CAIRO_FORMAT_ARGB32, size.width, size.height, plane.stride);
-               if (!surface) {
-                       ERROR("Create cairo surface failed");
-                       return;
-               }
-
-               error = cairo_surface_write_to_png(surface, filename.c_str());
-               if (error != CAIRO_STATUS_SUCCESS) {
-                       ERROR("Captured image failed %d", error);
-                       return;
-               }
-
-               DEBUG("Captured image: width = %d, height = %d, filename = %s", size.width, size.height, filename.c_str());
+       auto filename = directory + "/" + generateFileName();
+       timer.reset(DELAY, [this, filename]() {
+               auto mainWindow = Singleton<UniversalSwitch>::instance().getMainWindow();
+               if (mainWindow)
+                       capture(filename, mainWindow->getDimensions().size);
+               else
+                       ERROR("No main window");
+
+               completed = true;
+               return ecore::TimerRepetitionPolicy::cancel;
+       });
+
+       return false;
+}
+
+
+void ScreenshotActivity::capture(const std::string &filename, Size size)
+{
+       auto screenshotHandle = std::unique_ptr<_efl_util_screenshot_h, int (*)(_efl_util_screenshot_h *)> {
+               efl_util_screenshot_initialize(size.width, size.height), efl_util_screenshot_deinitialize
+       };
+
+       if (!screenshotHandle) {
+               ERROR("Screenshot initialization failed");
+               return;
        }
 
-       std::string generateFileName()
-       {
-               auto now = std::chrono::system_clock::now();
-               auto formated = std::chrono::system_clock::to_time_t(now);
+       auto tbmSurface = std::unique_ptr<_tbm_surface, int (*)(_tbm_surface *)> {
+               efl_util_screenshot_take_tbm_surface(screenshotHandle.get()), tbm_surface_destroy
+       };
 
-               std::stringstream ss;
-               ss << std::put_time(std::localtime(&formated), "%Y%m%d-%H%M%S") << ".png";
-               return ss.str();
+       if (!tbmSurface) {
+               ERROR("Taking surface failed");
+               return;
        }
 
-       efl_util_screenshot_h screenshotHandle;
-       tbm_surface_h tbmSurface;
-       cairo_surface_t *surface;
-       Size size;
-       std::string filename;
-};
+       tbm_surface_info_s surfaceInfo;
+       auto error = tbm_surface_get_info(tbmSurface.get(), &surfaceInfo);
+
+       if (error != TBM_SURFACE_ERROR_NONE) {
+               ERROR("Get surface info failed");
+               return;
+       }
+
+       if (surfaceInfo.num_planes < 1) {
+               ERROR("No planes in surface");
+               return;
+       }
+
+       auto &plane = surfaceInfo.planes[0];
+       auto surface = std::unique_ptr<cairo_surface_t, void (*)(cairo_surface_t *)> {
+               cairo_image_surface_create_for_data(plane.ptr, CAIRO_FORMAT_ARGB32, size.width, size.height, plane.stride), cairo_surface_destroy
+       };
+
+       if (!surface) {
+               ERROR("Create cairo surface failed");
+               return;
+       }
+
+       error = cairo_surface_write_to_png(surface.get(), filename.c_str());
+
+       if (error != CAIRO_STATUS_SUCCESS) {
+               ERROR("Captured image failed %d", error);
+               return;
+       }
+
+       DEBUG("Captured image: width = %d, height = %d, filename = %s", size.width, size.height, filename.c_str());
+}
+
+std::string ScreenshotActivity::generateFileName()
+{
+       auto now = std::chrono::system_clock::now();
+       auto formated = std::chrono::system_clock::to_time_t(now);
+
+       std::stringstream ss;
+       ss << std::put_time(std::localtime(&formated), "%Y%m%d-%H%M%S") << ".png";
+       return ss.str();
+}
\ No newline at end of file