Improve screenshot feature

Ecore X functions are not used anymore. An Evas snapshot is created and
its data is stored when the RENDER POST event is invoked on the canvas.

It fixes the random black screenshot and the constant black region at
the bottom of the window (probably caused by some change made on the
title bar management, as it seems to be the exact size).
This commit is contained in:
Daniel Zaoui 2017-06-25 11:02:19 +03:00
parent 287e8498a7
commit 390739d795
1 changed files with 54 additions and 48 deletions

View File

@ -797,52 +797,41 @@ _main_loop_obj_highlight_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid E
WRAPPER_TO_XFER_MAIN_LOOP(_obj_highlight_cb)
static void
_main_loop_win_screenshot_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
typedef struct
{
uint64_t ptr64;
Eina_Debug_Session *session;
Evas_Object *snapshot;
int cid;
} Screenshot_Async_Info;
static void
_screenshot_pixels_cb(void *data, Evas *e, void *event_info)
{
unsigned int hdr_size = sizeof(uint64_t) + 5 * sizeof(int);
Evas_Event_Render_Post *post = event_info;
Screenshot_Async_Info *info = data;
Evas_Object *snapshot = info->snapshot;
struct tm *t = NULL;
time_t now = time(NULL);
uint64_t ptr64 = 0;
Ecore_Evas *ee = NULL;
Ecore_X_Image *img;
Ecore_X_Window_Attributes att;
unsigned char *img_src;
unsigned char *resp = NULL, *tmp;
int bpl = 0, rows = 0, bpp = 0;
const void *pixels;
int w, h, val;
unsigned int hdr_size = sizeof(uint64_t) + 5 * sizeof(int);
if (size != sizeof(uint64_t)) return;
memcpy(&ptr64, buffer, sizeof(ptr64));
Eo *e = (Eo *)SWAP_64(ptr64);
if (!efl_isa(e, EVAS_CANVAS_CLASS)) goto end;
ee = ecore_evas_ecore_evas_get(e);
if (!ee) goto end;
Ecore_X_Window win = (Ecore_X_Window) ecore_evas_window_get(ee);
if (!win)
{
printf("Can't grab window.\n");
goto end;
}
// Nothing was updated, so let's not bother sending nothingness
if (!post->updated_area) return;
pixels = evas_object_image_data_get(snapshot, EINA_FALSE);
if (!pixels) return;
evas_object_geometry_get(snapshot, NULL, NULL, &w, &h);
t = localtime(&now);
t->tm_zone = NULL;
memset(&att, 0, sizeof(Ecore_X_Window_Attributes));
ecore_x_window_attributes_get(win, &att);
w = att.w;
h = att.h;
img = ecore_x_image_new(w, h, att.visual, att.depth);
ecore_x_image_get(img, win, 0, 0, 0, 0, w, h);
img_src = ecore_x_image_data_get(img, &bpl, &rows, &bpp);
resp = tmp = malloc(hdr_size + (w * h * sizeof(int)));
t->tm_sec = SWAP_32(t->tm_sec);
t->tm_min = SWAP_32(t->tm_min);
t->tm_hour = SWAP_32(t->tm_hour);
STORE(tmp, &ptr64, sizeof(ptr64));
STORE(tmp, &info->ptr64, sizeof(uint64_t));
STORE(tmp, &t->tm_sec, sizeof(int));
STORE(tmp, &t->tm_min, sizeof(int));
STORE(tmp, &t->tm_hour, sizeof(int));
@ -850,25 +839,42 @@ _main_loop_win_screenshot_cb(Eina_Debug_Session *session, int srcid, void *buffe
STORE(tmp, &val, sizeof(int));
val = SWAP_32(h);
STORE(tmp, &val, sizeof(int));
if (!ecore_x_image_is_argb32_get(img))
{ /* Fill resp buffer with image convert */
ecore_x_image_to_argb_convert(img_src, bpp, bpl, att.colormap, att.visual,
0, 0, w, h, (unsigned int *)tmp,
(w * sizeof(int)), 0, 0);
}
else
{ /* Fill resp buffer by copy */
memcpy(tmp, img_src, (w * h * sizeof(int)));
}
memcpy(tmp, pixels, (w * h * sizeof(int)));
/* resp now holds window bitmap */
ecore_x_image_free(img);
eina_debug_session_send(session, srcid, _win_screenshot_op, resp,
eina_debug_session_send(info->session, info->cid, _win_screenshot_op, resp,
hdr_size + (w * h * sizeof(int)));
end:
if (resp) free(resp);
evas_object_del(info->snapshot);
evas_event_callback_del_full(e, EVAS_CALLBACK_RENDER_POST, _screenshot_pixels_cb, info);
}
static void
_main_loop_win_screenshot_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
{
uint64_t ptr64;
Screenshot_Async_Info *info;
Evas_Object *snapshot;
int w, h;
if (size != sizeof(uint64_t)) return;
memcpy(&ptr64, buffer, sizeof(ptr64));
Eo *e = (Eo *)SWAP_64(ptr64);
if (!efl_isa(e, EVAS_CANVAS_CLASS)) return;
snapshot = evas_object_image_filled_add(e);
if (!snapshot) return;
evas_object_image_snapshot_set(snapshot, EINA_TRUE);
info = calloc(1, sizeof(*info));
info->ptr64 = ptr64;
info->snapshot = snapshot;
info->session = session;
info->cid = srcid;
evas_output_size_get(e, &w, &h);
evas_object_geometry_set(snapshot, 0, 0, w, h);
efl_gfx_visible_set(snapshot, EINA_TRUE);
evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, _screenshot_pixels_cb, info);
}
WRAPPER_TO_XFER_MAIN_LOOP(_win_screenshot_cb)