From fbaa8984dfaf0dea27c7e865d77f10e2ae347b70 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Sat, 5 Sep 2020 15:51:47 +0100 Subject: [PATCH] shot - allow copy of image to selection in addition to shave and share uses elm cnp to store the image in a selection attached to your compositor elm win. note... some apps are fussy about what file formats they accept... we've found through much pain that chrome (and i assume anything based on it like electron) only accept png for cnp. firefox accepts most sane formats (png, jpg). libreoffice too accepts png and jpg, efl accept sjust anout anything you throw at it, so ymmv. if paste doesnt work either the target for paste doesn't support pasting images at all or it is fussy about formats - maybe set quality to 100% to force png and try that as shot saves just png and jpg (100% quality == png, evrything below is jpg). if you want pastes of lower quality to work e.g. jpegs in chrome - file a bug with the chrome team... :) --- src/modules/shot/e_mod_main.h | 6 ++-- src/modules/shot/e_mod_preview.c | 10 +++++- src/modules/shot/e_mod_save.c | 31 +++++++++-------- src/modules/shot/e_mod_share.c | 57 ++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/src/modules/shot/e_mod_main.h b/src/modules/shot/e_mod_main.h index 279208f61..455c96f68 100644 --- a/src/modules/shot/e_mod_main.h +++ b/src/modules/shot/e_mod_main.h @@ -11,7 +11,7 @@ extern E_Module *shot_module; #define MAXZONES 64 -void share_save (const char *cmd); +void share_save (const char *cmd, const char *file, Eina_Bool copy); void share_write_end_watch (void *data); void share_write_status_watch(void *data); void share_dialog_show (void); @@ -22,8 +22,8 @@ void preview_dialog_show (E_Zone *zone, E_Client *ec, const char *pa Eina_Bool preview_have (void); void preview_abort (void); Evas_Object *preview_image_get (void); -void save_to (const char *file); -void save_show (void); +void save_to (const char *file, Eina_Bool copy); +void save_show (Eina_Bool save); Evas_Object *ui_edit(Evas_Object *window, Evas_Object *o_bg, E_Zone *zone, E_Client *ec, void *dst, int sx, int sy, int sw, int sh, diff --git a/src/modules/shot/e_mod_preview.c b/src/modules/shot/e_mod_preview.c index 25cc44e92..52fc0418d 100644 --- a/src/modules/shot/e_mod_preview.c +++ b/src/modules/shot/e_mod_preview.c @@ -9,7 +9,13 @@ Eina_Rectangle crop = { 0, 0, 0, 0 }; static void _win_save_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED) { - save_show(); + save_show(EINA_FALSE); +} + +static void +_win_copy_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED) +{ + save_show(EINA_TRUE); } static void @@ -88,6 +94,8 @@ preview_dialog_show(E_Zone *zone, E_Client *ec, const char *params, void *dst, e_widget_list_object_append(o_box, o, 1, 0, 0.5); o = e_widget_button_add(evas, _("Share"), NULL, _win_share_cb, win, NULL); e_widget_list_object_append(o_box, o, 1, 0, 0.5); + o = e_widget_button_add(evas, _("Copy"), NULL, _win_copy_cb, win, NULL); + e_widget_list_object_append(o_box, o, 1, 0, 0.5); if (!ec) { o = e_widget_button_add(evas, _("Delay"), NULL, _win_delay_cb, win, NULL); diff --git a/src/modules/shot/e_mod_save.c b/src/modules/shot/e_mod_save.c index fd2f4fbf1..47ed96ca2 100644 --- a/src/modules/shot/e_mod_save.c +++ b/src/modules/shot/e_mod_save.c @@ -7,6 +7,7 @@ typedef struct int w, h, stride, quality; size_t size; int fd; + Eina_Bool copy; } Rgba_Writer_Data; static void @@ -43,7 +44,7 @@ _cb_rgba_writer_done(void *data, Ecore_Thread *th EINA_UNUSED) e_module_dir_get(shot_module), MODULE_ARCH, rdata->path, rdata->w, rdata->h, rdata->stride, rdata->quality); - share_save(buf); + share_save(buf, rdata->outfile, rdata->copy); _rgba_data_free(rdata); } @@ -55,7 +56,7 @@ _cb_rgba_writer_cancel(void *data, Ecore_Thread *th EINA_UNUSED) } void -save_to(const char *file) +save_to(const char *file, Eina_Bool copy) { int fd; char tmpf[256] = "e-shot-rgba-XXXXXX"; @@ -71,7 +72,6 @@ save_to(const char *file) Evas_Object *img = preview_image_get(); ui_edit_prepare(); - printf("C: %i %i %ix%i\n", crop.x, crop.y, crop.w, crop.h); if ((crop.x == 0) && (crop.y == 0) && (crop.w == 0) && (crop.h == 0)) { @@ -115,7 +115,6 @@ save_to(const char *file) imh = crop.h; imstride = imw * 4; d = data; - printf("Cpy dat %p -> %p | %ix%i\n", src_data, data, imw, imh); for (y = crop.y; y < (crop.y + crop.h); y++) { s = src_data + (stride * y) + (crop.x * 4); @@ -144,6 +143,7 @@ save_to(const char *file) thdat->h = imh; thdat->stride = imstride; thdat->quality = quality; + thdat->copy = copy; ecore_thread_run(_cb_rgba_writer_do, _cb_rgba_writer_done, _cb_rgba_writer_cancel, thdat); @@ -167,7 +167,7 @@ save_to(const char *file) } void -save_show(void) +save_show(Eina_Bool copy) { char path[PATH_MAX + 512]; char path2[PATH_MAX + 512]; @@ -185,21 +185,24 @@ save_show(void) else strftime(buf, sizeof(buf), "shot-%Y-%m-%d_%H-%M-%S.jpg", tm); e_user_dir_snprintf(path, sizeof(path), "shots/%s", buf); - save_to(path); + save_to(path, copy); snprintf(path, sizeof(path), "%s/shots.desktop", e_module_dir_get(shot_module)); snprintf(path2, sizeof(path2), "%s/fileman/favorites/shots.desktop", e_user_dir_get()); if (!ecore_file_exists(path2)) ecore_file_cp(path, path2); - a = e_action_find("fileman_show"); - if (a) + if (!copy) { - a->func.go(NULL, "$E_HOME_DIR/shots"); + a = e_action_find("fileman_show"); + if (a) + { + a->func.go(NULL, "$E_HOME_DIR/shots"); + } + else + e_util_dialog_show + (_("Error - No Filemanager"), + _("No filemanager action and/or module was found.
" + "Cannot show the location of your screenshots.")); } - else - e_util_dialog_show - (_("Error - No Filemanager"), - _("No filemanager action and/or module was found.
" - "Cannot show the location of your screenshots.")); preview_abort(); } diff --git a/src/modules/shot/e_mod_share.c b/src/modules/shot/e_mod_share.c index c814ab94a..6154ce85b 100644 --- a/src/modules/shot/e_mod_share.c +++ b/src/modules/shot/e_mod_share.c @@ -6,6 +6,8 @@ static Evas_Object *o_label = NULL; static Evas_Object *o_entry = NULL; static Eina_List *handlers = NULL; static char *url_ret = NULL; +static const char *cnp_file = NULL; +static Eina_Bool cnp = EINA_FALSE; // clean up and be done static void @@ -19,6 +21,47 @@ _share_done(void) preview_abort(); } +static void +_cnp_thread_io(void *data, Ecore_Thread *eth EINA_UNUSED) +{ + char *file = data; + unsigned char *fdata = NULL; + ssize_t fsize = 0; + FILE *f = fopen(file, "r"); + + if (!f) goto err; + fseek(f, 0, SEEK_END); + fsize = ftell(f); + fseek(f, 0, SEEK_SET); + if (fsize > 0) + { + fdata = malloc(fsize); + if (fdata) + { + if (fread(fdata, fsize, 1, f) == 1) + { + ecore_thread_main_loop_begin(); + elm_cnp_selection_set(e_comp->elm, + ELM_SEL_TYPE_CLIPBOARD, + ELM_SEL_FORMAT_IMAGE, + fdata, fsize); + ecore_thread_main_loop_end(); + } + free(fdata); + } + } + fclose(f); + eina_file_unlink(file); +err: + free(file); +} + +static void +_cnp_file(const char *file) +{ + ecore_thread_run(_cnp_thread_io, NULL, NULL, strdup(file)); +} + // the upload dialog static void _upload_ok_cb(void *data EINA_UNUSED, E_Dialog *dia) @@ -46,6 +89,11 @@ _img_write_end_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event) if (ev->exe != img_write_exe) return EINA_TRUE; _share_done(); + if (cnp) + { + _cnp_file(cnp_file); + eina_stringshare_replace(&cnp_file, NULL); + } return EINA_FALSE; } @@ -102,8 +150,13 @@ done: } void -share_save(const char *cmd) +share_save(const char *cmd, const char *file, Eina_Bool copy) { + if (copy) + { + eina_stringshare_replace(&cnp_file, file); + cnp = copy; + } share_write_end_watch(NULL); img_write_exe = ecore_exe_pipe_run (cmd, ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_READ_LINE_BUFFERED | @@ -142,7 +195,7 @@ share_dialog_show(void) E_FREE_LIST(handlers, ecore_event_handler_del); - save_to(NULL); + save_to(NULL, EINA_FALSE); E_FREE_FUNC(win, evas_object_del);