Excellent !! :)

Btw, if someone wanted to get a jump on this, the "emprint" tool in git 
already has the ability to select a crop region ... someone could, if 
they wanted to, snarf some code out of emprint and implement that 
feature in E pretty easily ;)

Cheers,
dh


On 12/19/19 6:25 PM, Carsten Haitzler wrote:
> raster pushed a commit to branch master.
> 
> https://protect2.fireeye.com/url?k=dcbf7a16-81717bc5-dcbef159-000babff317b-4e052b12d58063b7&u=http://git.enlightenment.org/core/enlightenment.git/commit/?id=7227aaeb813fddb6a42da848152bfecf4a9497e8
> 
> commit 7227aaeb813fddb6a42da848152bfecf4a9497e8
> Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
> Date:   Wed Dec 18 19:01:40 2019 +0000
> 
>      shot - move save of shot and upload to slave binary tool and tidy code
>      
>      this gets rid of that annoying freeze in e due to the sync save and
>      possibly sync dns lookups in curl. slave binary handles it now and
>      talks back to e via stdout.
>      
>      this also splits up the code into more files for specific purposes to
>      make it easier to add features to and maintain. given on the todo is
>      the ability to explicitly select a crop region and do some basic
>      "drawing" too, this sets the stage for that and it made it easier to
>      do the above upload/save tool.
> ---
>   src/modules/shot/e_mod_main.c    | 819 
> +--------------------------------------
>   src/modules/shot/e_mod_main.h    |  28 ++
>   src/modules/shot/e_mod_preview.c | 291 ++++++++++++++
>   src/modules/shot/e_mod_save.c    | 273 +++++++++++++
>   src/modules/shot/e_mod_share.c   | 217 +++++++++++
>   src/modules/shot/meson.build     |  18 +-
>   src/modules/shot/upload.c        | 208 ++++++++++
>   7 files changed, 1053 insertions(+), 801 deletions(-)
> 
> diff --git a/src/modules/shot/e_mod_main.c b/src/modules/shot/e_mod_main.c
> index f0ff786d2..ac3f9bcab 100644
> --- a/src/modules/shot/e_mod_main.c
> +++ b/src/modules/shot/e_mod_main.c
> @@ -8,807 +8,28 @@
>    *
>    * @}
>    */
> -#include "e.h"
> -#include <time.h>
> -#include <sys/mman.h>
> +#include "e_mod_main.h"
>   
> -#if defined(__FreeBSD__) || defined(__DragonFly__)
> -#include <sys/types.h>
> -#include <sys/sysctl.h>
> -#endif
> -
> -static E_Module *shot_module = NULL;
> +E_Module *shot_module = NULL;
>   
>   static E_Action *border_act = NULL, *act = NULL;
>   static E_Int_Menu_Augmentation *maug = NULL;
>   static Ecore_Timer *timer, *border_timer = NULL;
> -static Evas_Object *win = NULL;
>   static Evas_Object *snap = NULL;
> -E_Confirm_Dialog *cd = NULL;
> -static Evas_Object *o_bg = NULL, *o_box = NULL, *o_content = NULL;
> -static Evas_Object *o_event = NULL, *o_img = NULL, *o_hlist = NULL;
> -static int quality = 90;
> -static int screen = -1;
> -#define MAXZONES 64
> -static Evas_Object *o_rectdim[MAXZONES] = { NULL };
> -static Evas_Object *o_radio_all = NULL;
> -static Evas_Object *o_radio[MAXZONES] = { NULL };
> -static Evas_Object *o_fsel = NULL;
> -static Evas_Object *o_label = NULL;
> -static Evas_Object *o_entry = NULL;
> -static unsigned char *fdata = NULL;
> -static int fsize = 0;
> -static Ecore_Con_Url *url_up = NULL;
> -static Eina_List *handlers = NULL;
> -static char *url_ret = NULL;
> -static E_Dialog *fsel_dia = NULL;
>   static E_Client_Menu_Hook *border_hook = NULL;
>   
>   static E_Client *shot_ec = NULL;
>   static E_Zone *shot_zone = NULL;
>   static char *shot_params;
>   
> -static void _file_select_ok_cb(void *data EINA_UNUSED, E_Dialog *dia);
> -static void _file_select_cancel_cb(void *data EINA_UNUSED, E_Dialog *dia);
> -
> -static void
> -_win_cancel_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED)
> -{
> -   E_FREE_FUNC(win, evas_object_del);
> -}
> -
> -static void
> -_win_delete_cb()
> -{
> -   win = NULL;
> -}
> -
> -static void
> -_on_focus_cb(void *data EINA_UNUSED, Evas_Object *obj)
> -{
> -   if (obj == o_content) e_widget_focused_object_clear(o_box);
> -   else if (o_content) e_widget_focused_object_clear(o_content);
> -}
> -
> -static void
> -_key_down_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj 
> EINA_UNUSED, void *event)
> -{
> -   Evas_Event_Key_Down *ev = event;
> -
> -   if (!strcmp(ev->key, "Tab"))
> -     {
> -        if 
> (evas_key_modifier_is_set(evas_key_modifier_get(evas_object_evas_get(win)), 
> "Shift"))
> -          {
> -             if (e_widget_focus_get(o_box))
> -               {
> -                  if (!e_widget_focus_jump(o_box, 0))
> -                    {
> -                       e_widget_focus_set(o_content, 0);
> -                       if (!e_widget_focus_get(o_content))
> -                          e_widget_focus_set(o_box, 0);
> -                    }
> -               }
> -             else
> -               {
> -                  if (!e_widget_focus_jump(o_content, 0))
> -                     e_widget_focus_set(o_box, 0);
> -               }
> -          }
> -        else
> -          {
> -             if (e_widget_focus_get(o_box))
> -               {
> -                  if (!e_widget_focus_jump(o_box, 1))
> -                    {
> -                       e_widget_focus_set(o_content, 1);
> -                       if (!e_widget_focus_get(o_content))
> -                          e_widget_focus_set(o_box, 1);
> -                    }
> -               }
> -             else
> -               {
> -                  if (!e_widget_focus_jump(o_content, 1))
> -                     e_widget_focus_set(o_box, 1);
> -               }
> -          }
> -     }
> -   else if (((!strcmp(ev->key, "Return")) ||
> -             (!strcmp(ev->key, "KP_Enter")) ||
> -             (!strcmp(ev->key, "space"))))
> -     {
> -        Evas_Object *o = NULL;
> -
> -        if ((o_content) && (e_widget_focus_get(o_content)))
> -          o = e_widget_focused_object_get(o_content);
> -        else
> -          o = e_widget_focused_object_get(o_box);
> -        if (o) e_widget_activate(o);
> -     }
> -   else if (!strcmp(ev->key, "Escape"))
> -     _win_cancel_cb(NULL, NULL);
> -}
> -
> -static void
> -_save_key_down_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object 
> *obj EINA_UNUSED, void *event)
> -{
> -   Evas_Event_Key_Down *ev = event;
> -
> -   if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
> -     _file_select_ok_cb(NULL, fsel_dia);
> -   else if (!strcmp(ev->key, "Escape"))
> -     _file_select_cancel_cb(NULL, fsel_dia);
> -}
> -
> -static void
> -_screen_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
> *event_info EINA_UNUSED)
> -{
> -   Eina_List *l;
> -   E_Zone *z;
> -
> -   EINA_LIST_FOREACH(e_comp->zones, l, z)
> -     {
> -        if (screen == -1)
> -          evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> -        else if (screen == (int)z->num)
> -          evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> -        else
> -          evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 200);
> -     }
> -}
> -
> -static void
> -_save_to(const char *file)
> -{
> -   char opts[256];
> -
> -   if (eina_str_has_extension(file, ".png"))
> -     snprintf(opts, sizeof(opts), "compress=%i", 9);
> -   else
> -     snprintf(opts, sizeof(opts), "quality=%i", quality);
> -   if (screen == -1)
> -     {
> -        if (o_img)
> -          {
> -             if (!evas_object_image_save(o_img, file, NULL, opts))
> -               e_util_dialog_show(_("Error saving screenshot file"),
> -                                  _("Path: %s"), file);
> -          }
> -     }
> -   else
> -     {
> -        Evas_Object *o;
> -        Eina_List *l;
> -        E_Zone *z = NULL;
> -
> -        EINA_LIST_FOREACH(e_comp->zones, l, z)
> -          {
> -             if (screen == (int)z->num) break;
> -             z = NULL;
> -          }
> -        if (z)
> -          {
> -             unsigned char *src, *dst, *s, *d;
> -             int sstd, dstd, y;
> -
> -             o = evas_object_image_add(evas_object_evas_get(o_img));
> -             evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
> -             evas_object_image_alpha_set(o, EINA_FALSE);
> -             evas_object_image_size_set(o, z->w, z->h);
> -             dstd = evas_object_image_stride_get(o);
> -             src = evas_object_image_data_get(o_img, EINA_FALSE);
> -             sstd = evas_object_image_stride_get(o_img);
> -             dst = evas_object_image_data_get(o, EINA_TRUE);
> -             if ((dstd > 0) && (sstd > 0) && (src) && (dst))
> -               {
> -                  d = dst;
> -                  for (y = z->y; y < z->y + z->h; y++)
> -                    {
> -                       s = src + (sstd * y) + (z->x * 4);
> -                       memcpy(d, s, z->w * 4);
> -                       d += dstd;
> -                    }
> -                  if (!evas_object_image_save(o, file, NULL, opts))
> -                    e_util_dialog_show(_("Error saving screenshot file"),
> -                                       _("Path: %s"), file);
> -               }
> -
> -             evas_object_del(o);
> -          }
> -     }
> -}
> -
> -static void
> -_file_select_ok_cb(void *data EINA_UNUSED, E_Dialog *dia)
> -{
> -   const char *file;
> -
> -   dia = fsel_dia;
> -   file = e_widget_fsel_selection_path_get(o_fsel);
> -   if ((!file) || (!file[0]) ||
> -       ((!eina_str_has_extension(file, ".jpg")) &&
> -           (!eina_str_has_extension(file, ".png"))))
> -     {
> -        e_util_dialog_show
> -        (_("Error - Unknown format"),
> -            _("File has an unspecified extension.<ps/>"
> -              "Please use '.jpg' or '.png' extensions<ps/>"
> -              "only as other formats are not<ps/>"
> -              "supported currently."));
> -        return;
> -     }
> -   _save_to(file);
> -   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> -   E_FREE_FUNC(win, evas_object_del);
> -   fsel_dia = NULL;
> -}
> -
> -static void
> -_file_select_cancel_cb(void *data EINA_UNUSED, E_Dialog *dia)
> -{
> -   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> -   fsel_dia = NULL;
> -}
> -
> -static void
> -_file_select_del_cb(void *d EINA_UNUSED)
> -{
> -   fsel_dia = NULL;
> -}
> -
> -static void
> -_win_save_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED)
> -{
> -   E_Dialog *dia;
> -   Evas_Object *o;
> -   Evas_Coord mw, mh;
> -   int mask = 0;
> -   time_t tt;
> -   struct tm *tm;
> -   char buf[PATH_MAX];
> -
> -   time(&tt);
> -   tm = localtime(&tt);
> -   if (quality == 100)
> -     strftime(buf, sizeof(buf), "shot-%Y-%m-%d_%H-%M-%S.png", tm);
> -   else
> -     strftime(buf, sizeof(buf), "shot-%Y-%m-%d_%H-%M-%S.jpg", tm);
> -   fsel_dia = dia = e_dialog_new(NULL, "E", "_e_shot_fsel");
> -   e_dialog_resizable_set(dia, EINA_TRUE);
> -   e_dialog_title_set(dia, _("Select screenshot save location"));
> -   o = e_widget_fsel_add(evas_object_evas_get(dia->win), "desktop", "/",
> -                         buf, NULL, NULL, NULL, NULL, NULL, 1);
> -   e_object_del_attach_func_set(E_OBJECT(dia), _file_select_del_cb);
> -   e_widget_fsel_window_set(o, dia->win);
> -   o_fsel = o;
> -   evas_object_show(o);
> -   e_widget_size_min_get(o, &mw, &mh);
> -   e_dialog_content_set(dia, o, mw, mh);
> -   e_dialog_button_add(dia, _("Save"), NULL,
> -                       _file_select_ok_cb, NULL);
> -   e_dialog_button_add(dia, _("Cancel"), NULL,
> -                       _file_select_cancel_cb, NULL);
> -   elm_win_center(dia->win, 1, 1);
> -   o = evas_object_rectangle_add(evas_object_evas_get(dia->win));
> -   if (!evas_object_key_grab(o, "Return", mask, ~mask, 0))
> -     printf("grab err\n");
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "KP_Enter", mask, ~mask, 0))
> -     printf("grab err\n");
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "Escape", mask, ~mask, 0))
> -     printf("grab err\n");
> -   evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN,
> -                                  _save_key_down_cb, NULL);
> -   e_dialog_show(dia);
> -}
> -
> -static void
> -_share_done(void)
> -{
> -   E_FREE_LIST(handlers, ecore_event_handler_del);
> -   o_label = NULL;
> -   E_FREE(url_ret);
> -   E_FREE_FUNC(url_up, ecore_con_url_free);
> -   url_up = NULL;
> -}
> -
> -static void
> -_upload_ok_cb(void *data EINA_UNUSED, E_Dialog *dia)
> -{
> -   // ok just hides dialog and does background upload
> -   o_label = NULL;
> -   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> -   if (!win) return;
> -   E_FREE_FUNC(win, evas_object_del);
> -}
> -
> -static void
> -_upload_cancel_cb(void *data EINA_UNUSED, E_Dialog *dia)
> -{
> -   o_label = NULL;
> -   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> -   E_FREE_FUNC(win, evas_object_del);
> -   _share_done();
> -}
> -
> -static Eina_Bool
> -_upload_data_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
> -{
> -   Ecore_Con_Event_Url_Data *ev = event;
> -
> -   if (ev->url_con != url_up) return EINA_TRUE;
> -   if ((o_label) && (ev->size < 1024))
> -     {
> -        char *txt = alloca(ev->size + 1);
> -
> -        memcpy(txt, ev->data, ev->size);
> -        txt[ev->size] = 0;
> -/*
> -        printf("GOT %i bytes: '%s'\n", ev->size, txt);
> -        int i;
> -        for (i = 0; i < ev->size; i++) printf("%02x.", ev->data[i]);
> -        printf("\n");
> - */
> -        if (!url_ret) url_ret = strdup(txt);
> -        else
> -          {
> -             char *n;
> -
> -             n = malloc(strlen(url_ret) + ev->size + 1);
> -             if (n)
> -               {
> -                  strcpy(n, url_ret);
> -                  free(url_ret);
> -                  strcat(n, txt);
> -                  url_ret = n;
> -               }
> -          }
> -     }
> -   return EINA_FALSE;
> -}
> -
> -static Eina_Bool
> -_upload_progress_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void 
> *event)
> -{
> -   size_t total, current;
> -   Ecore_Con_Event_Url_Progress *ev = event;
> -
> -   if (ev->url_con != url_up) return ECORE_CALLBACK_RENEW;
> -   total = ev->up.total;
> -   current = ev->up.now;
> -   if (o_label)
> -     {
> -        char buf[1024];
> -        char *buf_now, *buf_total;
> -
> -        buf_now = e_util_size_string_get(current);
> -        buf_total = e_util_size_string_get(total);
> -        snprintf(buf, sizeof(buf), _("Uploaded %s / %s"), buf_now, 
> buf_total);
> -        E_FREE(buf_now);
> -        E_FREE(buf_total);
> -        e_widget_label_text_set(o_label, buf);
> -     }
> -   return ECORE_CALLBACK_RENEW;
> -}
> -
> -static Eina_Bool
> -_upload_complete_cb(void *data, int ev_type EINA_UNUSED, void *event)
> -{
> -   int status;
> -   Ecore_Con_Event_Url_Complete *ev = event;
> -
> -   if (ev->url_con != url_up) return ECORE_CALLBACK_RENEW;
> -   status = ev->status;
> -
> -   if (data)
> -     e_widget_disabled_set(data, 1);
> -   if (status != 200)
> -     {
> -        e_util_dialog_show(_("Error - Upload Failed"),
> -                           _("Upload failed with status code:<ps/>"
> -                             "%i"), status);
> -        _share_done();
> -        return EINA_FALSE;
> -     }
> -   if ((o_entry) && (url_ret))
> -      e_widget_entry_text_set(o_entry, url_ret);
> -   _share_done();
> -   return ECORE_CALLBACK_RENEW;
> -}
> -
> -static void
> -_win_share_del(void *data EINA_UNUSED)
> -{
> -   if (handlers)
> -     ecore_event_handler_data_set(eina_list_last_data_get(handlers), NULL);
> -   _upload_cancel_cb(NULL, NULL);
> -   if (cd) e_object_del(E_OBJECT(cd));
> -}
> -
> -static void
> -_win_share_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED)
> -{
> -   E_Dialog *dia;
> -   Evas_Object *o, *ol;
> -   Evas_Coord mw, mh;
> -   char buf[PATH_MAX];
> -   FILE *f;
> -   int i, fd = -1;
> -
> -   srand(time(NULL));
> -   for (i = 0; i < 10240; i++)
> -     {
> -        int v = rand();
> -
> -        if (quality == 100)
> -          snprintf(buf, sizeof(buf), "/tmp/e-shot-%x.png", v);
> -        else
> -          snprintf(buf, sizeof(buf), "/tmp/e-shot-%x.jpg", v);
> -        fd = open(buf, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
> -        if (fd >= 0) break;
> -     }
> -   if (fd < 0)
> -     {
> -        e_util_dialog_show(_("Error - Can't create file"),
> -                           _("Cannot create temporary file '%s': %s"),
> -                           buf, strerror(errno));
> -        E_FREE_FUNC(win, evas_object_del);
> -        return;
> -     }
> -   _save_to(buf);
> -   E_FREE_FUNC(win, evas_object_del);
> -   f = fdopen(fd, "rb");
> -   if (!f)
> -     {
> -        e_util_dialog_show(_("Error - Can't open file"),
> -                           _("Cannot open temporary file '%s': %s"),
> -                           buf, strerror(errno));
> -        return;
> -     }
> -   fseek(f, 0, SEEK_END);
> -   fsize = ftell(f);
> -   if (fsize < 1)
> -     {
> -        e_util_dialog_show(_("Error - Bad size"),
> -                           _("Cannot get size of file '%s'"),
> -                           buf);
> -        fclose(f);
> -        return;
> -     }
> -   rewind(f);
> -   free(fdata);
> -   fdata = malloc(fsize);
> -   if (!fdata)
> -     {
> -        e_util_dialog_show(_("Error - Can't allocate memory"),
> -                           _("Cannot allocate memory for picture: %s"),
> -                           strerror(errno));
> -        fclose(f);
> -        return;
> -     }
> -   if (fread(fdata, fsize, 1, f) != 1)
> -     {
> -        e_util_dialog_show(_("Error - Can't read picture"),
> -                           _("Cannot read picture"));
> -        E_FREE(fdata);
> -        fclose(f);
> -        return;
> -     }
> -   fclose(f);
> -   ecore_file_unlink(buf);
> -
> -   _share_done();
> -
> -   E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_DATA,
> -                         _upload_data_cb, NULL);
> -   E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_PROGRESS,
> -                         _upload_progress_cb, NULL);
> -
> -   url_up = 
> ecore_con_url_new("https://protect2.fireeye.com/url?k=d49fc69a-8951c749-d49e4dd5-000babff317b-084fde3e78e5eb55&u=https://www.enlightenment.org/shot.php";);
> -   // why use http 1.1? proxies like squid don't handle 1.1 posts with expect
> -   // like curl uses by default, so go to 1.0 and this all works dandily
> -   // out of the box
> -   ecore_con_url_http_version_set(url_up, ECORE_CON_URL_HTTP_VERSION_1_0);
> -   ecore_con_url_post(url_up, fdata, fsize, "application/x-e-shot");
> -   dia = e_dialog_new(NULL, "E", "_e_shot_share");
> -   e_dialog_resizable_set(dia, EINA_TRUE);
> -   e_dialog_title_set(dia, _("Uploading screenshot"));
> -
> -   o = e_widget_list_add(evas_object_evas_get(dia->win), 0, 0);
> -   ol = o;
> -
> -   o = e_widget_label_add(evas_object_evas_get(dia->win), _("Uploading 
> ..."));
> -   o_label = o;
> -   e_widget_list_object_append(ol, o, 0, 0, 0.5);
> -
> -   o = e_widget_label_add(evas_object_evas_get(dia->win),
> -                          _("Screenshot is available at this location:"));
> -   e_widget_list_object_append(ol, o, 0, 0, 0.5);
> -
> -   o = e_widget_entry_add(dia->win, NULL, NULL, NULL, NULL);
> -   o_entry = o;
> -   e_widget_list_object_append(ol, o, 1, 0, 0.5);
> -
> -   e_widget_size_min_get(ol, &mw, &mh);
> -   e_dialog_content_set(dia, ol, mw, mh);
> -   e_dialog_button_add(dia, _("Hide"), NULL, _upload_ok_cb, NULL);
> -   e_dialog_button_add(dia, _("Cancel"), NULL, _upload_cancel_cb, NULL);
> -   e_object_del_attach_func_set(E_OBJECT(dia), _win_share_del);
> -   E_LIST_HANDLER_APPEND(handlers, ECORE_CON_EVENT_URL_COMPLETE,
> -                         _upload_complete_cb,
> -                         eina_list_last_data_get(dia->buttons));
> -   elm_win_center(dia->win, 1, 1);
> -   e_dialog_show(dia);
> -}
> -
> -static void
> -_win_share_confirm_del(void *d EINA_UNUSED)
> -{
> -   cd = NULL;
> -}
> -
> -static void
> -_win_share_confirm_yes(void *d EINA_UNUSED)
> -{
> -   _win_share_cb(NULL, NULL);
> -}
> -
> -static void
> -_win_share_confirm_cb(void *d EINA_UNUSED, void *d2 EINA_UNUSED)
> -{
> -   if (cd) return;
> -   cd = e_confirm_dialog_show(_("Confirm Share"), NULL,
> -                              _("This image will be uploaded<ps/>"
> -                                "to enlightenment.org. It will be publicly 
> visible."),
> -                              _("Confirm"), _("Cancel"),
> -                              _win_share_confirm_yes, NULL,
> -                              NULL, NULL, _win_share_confirm_del, NULL);
> -}
> -
> -static void
> -_rect_down_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj 
> EINA_UNUSED, void *event_info)
> -{
> -   Evas_Event_Mouse_Down *ev = event_info;
> -   Eina_List *l;
> -   E_Zone *z;
> -
> -   if (ev->button != 1) return;
> -
> -   e_widget_radio_toggle_set(o_radio_all, 0);
> -   EINA_LIST_FOREACH(e_comp->zones, l, z)
> -     {
> -        if (obj == o_rectdim[z->num])
> -          {
> -             screen = z->num;
> -             e_widget_radio_toggle_set(o_radio[z->num], 1);
> -          }
> -        else
> -           e_widget_radio_toggle_set(o_radio[z->num], 0);
> -     }
> -
> -   EINA_LIST_FOREACH(e_comp->zones, l, z)
> -     {
> -        if (screen == -1)
> -           evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> -        else if (screen == (int)z->num)
> -           evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> -        else
> -           evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 200);
> -     }
> -}
> -
> -static void
> -_save_dialog_show(E_Zone *zone, E_Client *ec, const char *params, void *dst, 
> int sw, int sh)
> -{
> -   Evas *evas, *evas2;
> -   Evas_Object *o, *oa, *op, *ol;
> -   Evas_Modifier_Mask mask;
> -   E_Radio_Group *rg;
> -   int w, h;
> -   char smode[128], squal[128], sscreen[128];
> -
> -   win = elm_win_add(NULL, NULL, ELM_WIN_BASIC);
> -
> -   evas = evas_object_evas_get(win);
> -   elm_win_title_set(win, _("Where to put Screenshot..."));
> -   evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _win_delete_cb, 
> NULL);
> -   elm_win_center(win, 1, 1);
> -   ecore_evas_name_class_set(e_win_ee_get(win), "E", "_shot_dialog");
> -
> -   o = elm_layout_add(e_win_evas_win_get(evas));
> -   elm_win_resize_object_add(win, o);
> -   o_bg = o;;
> -   e_theme_edje_object_set(o, "base/theme/dialog", "e/widgets/dialog/main");
> -   evas_object_show(o);
> -
> -   o = e_widget_list_add(evas, 0, 0);
> -   o_content = o;
> -   elm_object_part_content_set(o_bg, "e.swallow.content", o);
> -   evas_object_show(o);
> -
> -   w = sw / 4;
> -   if (w < 220) w = 220;
> -   h = (w * sh) / sw;
> -
> -   o = e_widget_aspect_add(evas, w, h);
> -   oa = o;
> -   o = e_widget_preview_add(evas, w, h);
> -   op = o;
> -
> -   evas2 = e_widget_preview_evas_get(op);
> -
> -   o = evas_object_image_filled_add(evas2);
> -   o_img = o;
> -   evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
> -   evas_object_image_alpha_set(o, EINA_FALSE);
> -   evas_object_image_size_set(o, sw, sh);
> -   evas_object_image_data_copy_set(o, dst);
> -
> -   evas_object_image_data_update_add(o, 0, 0, sw, sh);
> -   e_widget_preview_extern_object_set(op, o);
> -   evas_object_show(o);
> -
> -   evas_object_show(op);
> -   evas_object_show(oa);
> -
> -   e_widget_aspect_child_set(oa, op);
> -   e_widget_list_object_append(o_content, oa, 0, 0, 0.5);
> -
> -   o = e_widget_list_add(evas, 1, 1);
> -   o_hlist = o;
> -
> -   o = e_widget_framelist_add(evas, _("Quality"), 0);
> -   ol = o;
> -
> -   rg = e_widget_radio_group_new(&quality);
> -   o = e_widget_radio_add(evas, _("Perfect"), 100, rg);
> -   e_widget_framelist_object_append(ol, o);
> -   o = e_widget_radio_add(evas, _("High"), 90, rg);
> -   e_widget_framelist_object_append(ol, o);
> -   o = e_widget_radio_add(evas, _("Medium"), 70, rg);
> -   e_widget_framelist_object_append(ol, o);
> -   o = e_widget_radio_add(evas, _("Low"), 50, rg);
> -   e_widget_framelist_object_append(ol, o);
> -
> -   e_widget_list_object_append(o_hlist, ol, 1, 0, 0.5);
> -
> -   if (zone)
> -     {
> -        screen = -1;
> -        if (eina_list_count(e_comp->zones) > 1)
> -          {
> -             Eina_List *l;
> -             E_Zone *z;
> -             int i;
> -
> -             o = e_widget_framelist_add(evas, _("Screen"), 0);
> -             ol = o;
> -
> -             rg = e_widget_radio_group_new(&screen);
> -             o = e_widget_radio_add(evas, _("All"), -1, rg);
> -             o_radio_all = o;
> -             evas_object_smart_callback_add(o, "changed",
> -                                            _screen_change_cb, NULL);
> -             e_widget_framelist_object_append(ol, o);
> -             i = 0;
> -             EINA_LIST_FOREACH(e_comp->zones, l, z)
> -               {
> -                  char buf[32];
> -
> -                  if (z->num >= MAXZONES) continue;
> -                  snprintf(buf, sizeof(buf), "%i", z->num);
> -                  o = e_widget_radio_add(evas, buf, z->num, rg);
> -                  o_radio[z->num] = o;
> -                  evas_object_smart_callback_add(o, "changed",
> -                                                 _screen_change_cb, NULL);
> -                  e_widget_framelist_object_append(ol, o);
> -
> -                  o = evas_object_rectangle_add(evas2);
> -                  evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
> -                                                 _rect_down_cb, NULL);
> -                  o_rectdim[z->num] = o;
> -                  evas_object_color_set(o, 0, 0, 0, 0);
> -                  evas_object_show(o);
> -                  evas_object_geometry_get(o_img, NULL, NULL, &w, &h);
> -                  evas_object_move(o, (z->x * w) / sw, (z->y * h) / sh);
> -                  evas_object_resize(o, (z->w * w) / sw, (z->h * h) / sh);
> -                  i++;
> -               }
> -
> -             e_widget_list_object_append(o_hlist, ol, 1, 0, 0.5);
> -          }
> -
> -     }
> -   e_widget_list_object_append(o_content, o_hlist, 0, 0, 0.5);
> -
> -   o = o_content;
> -   e_widget_size_min_get(o, &w, &h);
> -   evas_object_size_hint_min_set(o, w, h);
> -   elm_object_part_content_set(o_bg, "e.swallow.content", o);
> -   evas_object_show(o);
> -
> -   ///////////////////////////////////////////////////////////////////////
> -
> -   o = e_widget_list_add(evas, 1, 1);
> -   o_box = o;
> -   e_widget_on_focus_hook_set(o, _on_focus_cb, NULL);
> -   elm_object_part_content_set(o_bg, "e.swallow.buttons", o);
> -
> -   o = e_widget_button_add(evas, _("Save"), NULL, _win_save_cb, win, NULL);
> -   e_widget_list_object_append(o_box, o, 1, 0, 0.5);
> -   o = e_widget_button_add(evas, _("Share"), NULL,
> -                           _win_share_confirm_cb, win, NULL);
> -   e_widget_list_object_append(o_box, o, 1, 0, 0.5);
> -   o = e_widget_button_add(evas, _("Cancel"), NULL, _win_cancel_cb, win, 
> NULL);
> -   e_widget_list_object_append(o_box, o, 1, 0, 0.5);
> -
> -   o = o_box;
> -   e_widget_size_min_get(o, &w, &h);
> -   evas_object_size_hint_min_set(o, w, h);
> -   elm_object_part_content_set(o_bg, "e.swallow.buttons", o);
> -
> -   o = evas_object_rectangle_add(evas);
> -   o_event = o;
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "Tab", mask, ~mask, 0)) printf("grab err\n");
> -   mask = evas_key_modifier_mask_get(evas, "Shift");
> -   if (!evas_object_key_grab(o, "Tab", mask, ~mask, 0)) printf("grab err\n");
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "Return", mask, ~mask, 0)) printf("grab 
> err\n");
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "KP_Enter", mask, ~mask, 0)) printf("grab 
> err\n");
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "space", mask, ~mask, 0)) printf("grab 
> err\n");
> -   mask = 0;
> -   if (!evas_object_key_grab(o, "Escape", mask, ~mask, 0)) printf("grab 
> err\n");
> -   evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, 
> NULL);
> -
> -   evas_object_size_hint_min_get(o_bg, &w, &h);
> -   evas_object_resize(o_bg, w, h);
> -   evas_object_resize(win, w, h);
> -   evas_object_size_hint_min_set(win, w, h);
> -   evas_object_size_hint_max_set(win, 99999, 99999);
> -
> -   if ((params) &&
> -       (sscanf(params, "%100s %100s %100s", smode, squal, sscreen) == 3))
> -     {
> -        screen = -1;
> -        if ((zone) && (!strcmp(sscreen, "current"))) screen = zone->num;
> -        else if (!strcmp(sscreen, "all")) screen = -1;
> -        else screen = atoi(sscreen);
> -
> -        quality = 90;
> -        if (!strcmp(squal, "perfect")) quality = 100;
> -        else if (!strcmp(squal, "high")) quality = 90;
> -        else if (!strcmp(squal, "medium")) quality = 70;
> -        else if (!strcmp(squal, "low")) quality = 50;
> -        else quality = atoi(squal);
> -
> -        if (!strcmp(smode, "save")) _win_save_cb(NULL, NULL);
> -        else if (!strcmp(smode, "share"))  _win_share_cb(NULL, NULL);
> -     }
> -   else
> -     {
> -        evas_object_show(win);
> -        e_win_client_icon_set(win, "screenshot");
> -
> -        if (!e_widget_focus_get(o_bg)) e_widget_focus_set(o_box, 1);
> -        if (ec)
> -          {
> -             E_Client *c = e_win_client_get(win);
> -
> -             if (c) evas_object_layer_set(c->frame, ec->layer);
> -          }
> -     }
> -}
> -
>   static void
>   _shot_post(void *buffer EINA_UNUSED, Evas *e EINA_UNUSED, void *event 
> EINA_UNUSED)
>   {
>      int w, h;
>      evas_object_geometry_get(snap, NULL, NULL, &w, &h);
>      evas_event_callback_del(e_comp->evas, EVAS_CALLBACK_RENDER_POST, 
> _shot_post);
> -   _save_dialog_show(shot_zone, shot_ec, shot_params, 
> (void*)evas_object_image_data_get(snap, 0), w, h);
> +   preview_dialog_show(shot_zone, shot_ec, shot_params,
> +                       (void *)evas_object_image_data_get(snap, 0), w, h);
>      E_FREE_FUNC(snap, evas_object_del);
>      shot_ec = NULL;
>      shot_zone = NULL;
> @@ -819,7 +40,7 @@ static void
>   _shot_now(E_Zone *zone, E_Client *ec, const char *params)
>   {
>      int x, y, w, h;
> -   if ((win) || (url_up) || snap) return;
> +   if (preview_have() || save_have() || share_have() || (snap)) return;
>      if ((!zone) && (!ec)) return;
>      if (zone)
>        {
> @@ -852,7 +73,9 @@ _shot_now(E_Zone *zone, E_Client *ec, const char *params)
>        }
>      if (eina_streq(ecore_evas_engine_name_get(e_comp->ee), "buffer"))
>        {
> -        _save_dialog_show(zone, ec, params, 
> (void*)ecore_evas_buffer_pixels_get(e_comp->ee), w, h);
> +        preview_dialog_show(zone, ec, params,
> +                            (void *)ecore_evas_buffer_pixels_get(e_comp->ee),
> +                            w, h);
>           return;
>        }
>      shot_ec = ec;
> @@ -979,12 +202,9 @@ _e_mod_action_cb(E_Object *obj, const char *params)
>   
>      if (obj)
>        {
> -        if (obj->type == E_COMP_TYPE)
> -          zone = e_zone_current_get();
> -        else if (obj->type == E_ZONE_TYPE)
> -          zone = ((void *)obj);
> -        else
> -          zone = e_zone_current_get();
> +        if (obj->type == E_COMP_TYPE) zone = e_zone_current_get();
> +        else if (obj->type == E_ZONE_TYPE) zone = ((void *)obj);
> +        else zone = e_zone_current_get();
>        }
>      if (!zone) zone = e_zone_current_get();
>      if (!zone) return;
> @@ -993,9 +213,8 @@ _e_mod_action_cb(E_Object *obj, const char *params)
>      e_object_ref(E_OBJECT(zone));
>      ds->zone = zone;
>      ds->params = params ? strdup(params) : NULL;
> -   /* forced main loop iteration in screenshots causes bugs if the action
> -    * executes immediately
> -    */
> +   // forced main loop iteration in screenshots causes bugs if the action
> +   // executes immediately
>      ecore_job_add(_delayed_shot, ds);
>   }
>   
> @@ -1010,9 +229,11 @@ _bd_hook(void *d EINA_UNUSED, E_Client *ec)
>      if (ec->iconic || (ec->desk != e_desk_current_get(ec->zone))) return;
>      m = ec->border_menu;
>   
> -   /* position menu item just before first separator */
> +   // position menu item just before first separator
>      EINA_LIST_FOREACH(m->items, l, mi)
> -     if (mi->separator) break;
> +     {
> +        if (mi->separator) break;
> +     }
>      if ((!mi) || (!mi->separator)) return;
>      l = eina_list_prev(l);
>      mi = eina_list_data_get(l);
> @@ -1083,9 +304,9 @@ e_modapi_init(E_Module *m)
>   E_API int
>   e_modapi_shutdown(E_Module *m EINA_UNUSED)
>   {
> -   _share_done();
> -   E_FREE_FUNC(win, evas_object_del);
> -   E_FREE_FUNC(cd, e_object_del);
> +   share_abort();
> +   save_abort();
> +   preview_abort();
>      if (timer)
>        {
>           ecore_timer_del(timer);
> diff --git a/src/modules/shot/e_mod_main.h b/src/modules/shot/e_mod_main.h
> new file mode 100644
> index 000000000..1a3ce1a09
> --- /dev/null
> +++ b/src/modules/shot/e_mod_main.h
> @@ -0,0 +1,28 @@
> +#include "e.h"
> +#include <time.h>
> +#include <sys/mman.h>
> +
> +#if defined(__FreeBSD__) || defined(__DragonFly__)
> +# include <sys/types.h>
> +# include <sys/sysctl.h>
> +#endif
> +
> +extern E_Module *shot_module;
> +
> +#define MAXZONES 64
> +
> +void         share_save              (const char *cmd);
> +void         share_write_end_watch   (void *data);
> +void         share_write_status_watch(void *data);
> +void         share_dialog_show       (void);
> +void         share_confirm           (void);
> +Eina_Bool    share_have              (void);
> +void         share_abort             (void);
> +void         preview_dialog_show     (E_Zone *zone, E_Client *ec, const char 
> *params, void *dst, int sw, int sh);
> +Eina_Bool    preview_have            (void);
> +void         preview_abort           (void);
> +Evas_Object *preview_image_get       (void);
> +void         save_to                 (const char *file);
> +void         save_dialog_show        (void);
> +Eina_Bool    save_have               (void);
> +void         save_abort              (void);
> diff --git a/src/modules/shot/e_mod_preview.c 
> b/src/modules/shot/e_mod_preview.c
> new file mode 100644
> index 000000000..9232a655d
> --- /dev/null
> +++ b/src/modules/shot/e_mod_preview.c
> @@ -0,0 +1,291 @@
> +#include "e_mod_main.h"
> +
> +static Evas_Object *win = NULL;
> +static Evas_Object *o_bg = NULL, *o_box = NULL, *o_content = NULL;
> +static Evas_Object *o_event = NULL, *o_img = NULL, *o_hlist = NULL;
> +static Evas_Object *o_rectdim[MAXZONES] = { NULL };
> +static Evas_Object *o_radio_all = NULL;
> +static Evas_Object *o_radio[MAXZONES] = { NULL };
> +static int          quality = 90;
> +static int          screen = -1;
> +
> +static void
> +_win_save_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED)
> +{
> +   save_dialog_show();
> +}
> +
> +static void
> +_win_share_cb(void *d EINA_UNUSED, void *d2 EINA_UNUSED)
> +{
> +   share_confirm();
> +}
> +
> +static void
> +_win_cancel_cb(void *data EINA_UNUSED, void *data2 EINA_UNUSED)
> +{
> +   E_FREE_FUNC(win, evas_object_del);
> +}
> +
> +static void
> +_win_delete_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj 
> EINA_UNUSED, void *event EINA_UNUSED)
> +{
> +   win = NULL;
> +}
> +
> +static void
> +_screen_change_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
> *event_info EINA_UNUSED)
> +{
> +   Eina_List *l;
> +   E_Zone *z;
> +
> +   EINA_LIST_FOREACH(e_comp->zones, l, z)
> +     {
> +        if (screen == -1)
> +          evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> +        else if (screen == (int)z->num)
> +          evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> +        else
> +          evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 200);
> +     }
> +}
> +
> +static void
> +_rect_down_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj 
> EINA_UNUSED, void *event_info)
> +{
> +   Evas_Event_Mouse_Down *ev = event_info;
> +   Eina_List *l;
> +   E_Zone *z;
> +
> +   if (ev->button != 1) return;
> +
> +   e_widget_radio_toggle_set(o_radio_all, 0);
> +   EINA_LIST_FOREACH(e_comp->zones, l, z)
> +     {
> +        if (obj == o_rectdim[z->num])
> +          {
> +             screen = z->num;
> +             e_widget_radio_toggle_set(o_radio[z->num], 1);
> +          }
> +        else
> +           e_widget_radio_toggle_set(o_radio[z->num], 0);
> +     }
> +
> +   EINA_LIST_FOREACH(e_comp->zones, l, z)
> +     {
> +        if (screen == -1)
> +           evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> +        else if (screen == (int)z->num)
> +           evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 0);
> +        else
> +           evas_object_color_set(o_rectdim[z->num], 0, 0, 0, 200);
> +     }
> +}
> +
> +void
> +preview_dialog_show(E_Zone *zone, E_Client *ec, const char *params, void 
> *dst,
> +                    int sw, int sh)
> +{
> +   Evas *evas, *evas2;
> +   Evas_Object *o, *oa, *op, *ol;
> +   E_Radio_Group *rg;
> +   int w, h;
> +   char smode[128], squal[128], sscreen[128];
> +
> +   win = elm_win_add(NULL, NULL, ELM_WIN_BASIC);
> +
> +   evas = evas_object_evas_get(win);
> +   elm_win_title_set(win, _("Select action to take with screenshot"));
> +   evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _win_delete_cb, 
> NULL);
> +   elm_win_center(win, 1, 1);
> +   ecore_evas_name_class_set(e_win_ee_get(win), "E", "_shot_dialog");
> +
> +   o = elm_layout_add(e_win_evas_win_get(evas));
> +   elm_win_resize_object_add(win, o);
> +   o_bg = o;
> +   e_theme_edje_object_set(o, "base/theme/dialog", "e/widgets/dialog/main");
> +   evas_object_show(o);
> +
> +   o = e_widget_list_add(evas, 0, 0);
> +   o_content = o;
> +   elm_object_part_content_set(o_bg, "e.swallow.content", o);
> +   evas_object_show(o);
> +
> +   w = sw / 4;
> +   if (w < 220) w = 220;
> +   h = (w * sh) / sw;
> +
> +   o = e_widget_aspect_add(evas, w, h);
> +   oa = o;
> +   o = e_widget_preview_add(evas, w, h);
> +   op = o;
> +
> +   evas2 = e_widget_preview_evas_get(op);
> +
> +   o = evas_object_image_filled_add(evas2);
> +   o_img = o;
> +   evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
> +   evas_object_image_alpha_set(o, EINA_FALSE);
> +   evas_object_image_size_set(o, sw, sh);
> +   evas_object_image_data_copy_set(o, dst);
> +
> +   evas_object_image_data_update_add(o, 0, 0, sw, sh);
> +   e_widget_preview_extern_object_set(op, o);
> +   evas_object_show(o);
> +
> +   evas_object_show(op);
> +   evas_object_show(oa);
> +
> +   e_widget_aspect_child_set(oa, op);
> +   e_widget_list_object_append(o_content, oa, 0, 0, 0.5);
> +
> +   o = e_widget_list_add(evas, 1, 1);
> +   o_hlist = o;
> +
> +   o = e_widget_framelist_add(evas, _("Quality"), 0);
> +   ol = o;
> +
> +   rg = e_widget_radio_group_new(&quality);
> +   o = e_widget_radio_add(evas, _("Perfect"), 100, rg);
> +   e_widget_framelist_object_append(ol, o);
> +   o = e_widget_radio_add(evas, _("High"), 90, rg);
> +   e_widget_framelist_object_append(ol, o);
> +   o = e_widget_radio_add(evas, _("Medium"), 70, rg);
> +   e_widget_framelist_object_append(ol, o);
> +   o = e_widget_radio_add(evas, _("Low"), 50, rg);
> +   e_widget_framelist_object_append(ol, o);
> +
> +   e_widget_list_object_append(o_hlist, ol, 1, 0, 0.5);
> +
> +   if (zone)
> +     {
> +        screen = -1;
> +        if (eina_list_count(e_comp->zones) > 1)
> +          {
> +             Eina_List *l;
> +             E_Zone *z;
> +             int i;
> +
> +             o = e_widget_framelist_add(evas, _("Screen"), 0);
> +             ol = o;
> +
> +             rg = e_widget_radio_group_new(&screen);
> +             o = e_widget_radio_add(evas, _("All"), -1, rg);
> +             o_radio_all = o;
> +             evas_object_smart_callback_add(o, "changed",
> +                                            _screen_change_cb, NULL);
> +             e_widget_framelist_object_append(ol, o);
> +             i = 0;
> +             EINA_LIST_FOREACH(e_comp->zones, l, z)
> +               {
> +                  char buf[32];
> +
> +                  if (z->num >= MAXZONES) continue;
> +                  snprintf(buf, sizeof(buf), "%i", z->num);
> +                  o = e_widget_radio_add(evas, buf, z->num, rg);
> +                  o_radio[z->num] = o;
> +                  evas_object_smart_callback_add(o, "changed",
> +                                                 _screen_change_cb, NULL);
> +                  e_widget_framelist_object_append(ol, o);
> +
> +                  o = evas_object_rectangle_add(evas2);
> +                  evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
> +                                                 _rect_down_cb, NULL);
> +                  o_rectdim[z->num] = o;
> +                  evas_object_color_set(o, 0, 0, 0, 0);
> +                  evas_object_show(o);
> +                  evas_object_geometry_get(o_img, NULL, NULL, &w, &h);
> +                  evas_object_move(o, (z->x * w) / sw, (z->y * h) / sh);
> +                  evas_object_resize(o, (z->w * w) / sw, (z->h * h) / sh);
> +                  i++;
> +               }
> +             e_widget_list_object_append(o_hlist, ol, 1, 0, 0.5);
> +          }
> +
> +     }
> +   e_widget_list_object_append(o_content, o_hlist, 0, 0, 0.5);
> +
> +   o = o_content;
> +   e_widget_size_min_get(o, &w, &h);
> +   evas_object_size_hint_min_set(o, w, h);
> +   elm_object_part_content_set(o_bg, "e.swallow.content", o);
> +   evas_object_show(o);
> +
> +   ///////////////////////////////////////////////////////////////////////
> +
> +   o = e_widget_list_add(evas, 1, 1);
> +   o_box = o;
> +   elm_object_part_content_set(o_bg, "e.swallow.buttons", o);
> +
> +   o = e_widget_button_add(evas, _("Save"), NULL, _win_save_cb, win, NULL);
> +   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, _("Cancel"), NULL, _win_cancel_cb, win, 
> NULL);
> +   e_widget_list_object_append(o_box, o, 1, 0, 0.5);
> +
> +   o = o_box;
> +   e_widget_size_min_get(o, &w, &h);
> +   evas_object_size_hint_min_set(o, w, h);
> +   elm_object_part_content_set(o_bg, "e.swallow.buttons", o);
> +
> +   o = evas_object_rectangle_add(evas);
> +   o_event = o;
> +
> +   evas_object_size_hint_min_get(o_bg, &w, &h);
> +   evas_object_resize(o_bg, w, h);
> +   evas_object_resize(win, w, h);
> +   evas_object_size_hint_min_set(win, w, h);
> +   evas_object_size_hint_max_set(win, 99999, 99999);
> +
> +   if ((params) &&
> +       (sscanf(params, "%100s %100s %100s", smode, squal, sscreen) == 3))
> +     {
> +        screen = -1;
> +        if ((zone) && (!strcmp(sscreen, "current"))) screen = zone->num;
> +        else if (!strcmp(sscreen, "all")) screen = -1;
> +        else screen = atoi(sscreen);
> +
> +        quality = 90;
> +        if (!strcmp(squal, "perfect")) quality = 100;
> +        else if (!strcmp(squal, "high")) quality = 90;
> +        else if (!strcmp(squal, "medium")) quality = 70;
> +        else if (!strcmp(squal, "low")) quality = 50;
> +        else quality = atoi(squal);
> +
> +        if (!strcmp(smode, "save")) _win_save_cb(NULL, NULL);
> +        else if (!strcmp(smode, "share"))  _win_share_cb(NULL, NULL);
> +     }
> +   else
> +     {
> +        evas_object_show(win);
> +        e_win_client_icon_set(win, "screenshot");
> +
> +        if (!e_widget_focus_get(o_bg)) e_widget_focus_set(o_box, 1);
> +        if (ec)
> +          {
> +             E_Client *c = e_win_client_get(win);
> +
> +             if (c) evas_object_layer_set(c->frame, ec->layer);
> +          }
> +     }
> +}
> +
> +Eina_Bool
> +preview_have(void)
> +{
> +   if (win) return EINA_TRUE;
> +   else return EINA_FALSE;
> +}
> +
> +void
> +preview_abort(void)
> +{
> +   E_FREE_FUNC(win, evas_object_del);
> +}
> +
> +Evas_Object *
> +preview_image_get(void)
> +{
> +   return o_img;
> +}
> diff --git a/src/modules/shot/e_mod_save.c b/src/modules/shot/e_mod_save.c
> new file mode 100644
> index 000000000..9736f0d2c
> --- /dev/null
> +++ b/src/modules/shot/e_mod_save.c
> @@ -0,0 +1,273 @@
> +#include "e_mod_main.h"
> +
> +static int          quality = 90;
> +static int          screen = -1;
> +static Evas_Object *o_fsel = NULL;
> +static E_Dialog    *fsel_dia = NULL;
> +
> +static void _file_select_ok_cb(void *data EINA_UNUSED, E_Dialog *dia);
> +static void _file_select_cancel_cb(void *data EINA_UNUSED, E_Dialog *dia);
> +
> +typedef struct
> +{
> +   char *path, *outfile;
> +   void *data;
> +   int w, h, stride, quality;
> +   size_t size;
> +   int fd;
> +} Rgba_Writer_Data;
> +
> +static void
> +_rgba_data_free(Rgba_Writer_Data *rdata)
> +{
> +   free(rdata->path);
> +   free(rdata->outfile);
> +   free(rdata->data);
> +   close(rdata->fd);
> +   free(rdata);
> +}
> +
> +static void
> +_cb_rgba_writer_do(void *data, Ecore_Thread *th EINA_UNUSED)
> +{
> +   Rgba_Writer_Data *rdata = data;
> +   if (write(rdata->fd, rdata->data, rdata->size) < 0)
> +     ERR("Write of shot rgba data failed");
> +}
> +
> +static void
> +_cb_rgba_writer_done(void *data, Ecore_Thread *th EINA_UNUSED)
> +{
> +   Rgba_Writer_Data *rdata = data;
> +   char buf[PATH_MAX];
> +
> +   if (rdata->outfile)
> +     snprintf(buf, sizeof(buf), "%s/%s/upload '%s' %i %i %i %i '%s'",
> +              e_module_dir_get(shot_module), MODULE_ARCH,
> +              rdata->path, rdata->w, rdata->h, rdata->stride,
> +              rdata->quality, rdata->outfile);
> +   else
> +     snprintf(buf, sizeof(buf), "%s/%s/upload '%s' %i %i %i %i",
> +              e_module_dir_get(shot_module), MODULE_ARCH,
> +              rdata->path, rdata->w, rdata->h, rdata->stride,
> +              rdata->quality);
> +   share_save(buf);
> +   _rgba_data_free(rdata);
> +}
> +
> +static void
> +_cb_rgba_writer_cancel(void *data, Ecore_Thread *th EINA_UNUSED)
> +{
> +   Rgba_Writer_Data *rdata = data;
> +   _rgba_data_free(rdata);
> +}
> +
> +void
> +save_to(const char *file)
> +{
> +   int fd;
> +   char tmpf[256] = "e-shot-rgba-XXXXXX";
> +   Eina_Tmpstr *path = NULL;
> +   int imw = 0, imh = 0, imstride;
> +
> +   fd = eina_file_mkstemp(tmpf, &path);
> +   if (fd >= 0)
> +     {
> +        unsigned char *data = NULL;
> +        Rgba_Writer_Data *thdat = NULL;
> +        size_t size = 0;
> +        Evas_Object *img = preview_image_get();
> +
> +        if (screen == -1)
> +          {
> +             if (img)
> +               {
> +                  int w = 0, h = 0;
> +                  int stride = evas_object_image_stride_get(img);
> +                  unsigned char *src_data = evas_object_image_data_get(img, 
> EINA_FALSE);
> +
> +                  evas_object_image_size_get(img, &w, &h);
> +                  if ((stride > 0) && (src_data) && (h > 0))
> +                    {
> +                       imw = w;
> +                       imh = h;
> +                       imstride = stride;
> +                       size = stride * h;
> +                       data = malloc(size);
> +                       if (data) memcpy(data, src_data, size);
> +                    }
> +               }
> +          }
> +        else
> +          {
> +             if (img)
> +               {
> +                  int w = 0, h = 0;
> +                  int stride = evas_object_image_stride_get(img);
> +                  unsigned char *src_data = evas_object_image_data_get(img, 
> EINA_FALSE);
> +
> +                  evas_object_image_size_get(img, &w, &h);
> +                  if ((stride > 0) && (src_data) && (h > 0))
> +                    {
> +                       Eina_List *l;
> +                       E_Zone *z = NULL;
> +
> +                       EINA_LIST_FOREACH(e_comp->zones, l, z)
> +                         {
> +                            if (screen == (int)z->num) break;
> +                            z = NULL;
> +                         }
> +                       if (z)
> +                         {
> +                            size = z->w * z->h * 4;
> +                            data = malloc(size);
> +                            if (data)
> +                              {
> +                                 int y;
> +                                 unsigned char *s, *d;
> +
> +                                 imw = z->w;
> +                                 imh = z->h;
> +                                 imstride = imw * 4;
> +                                 d = data;
> +                                 for (y = z->y; y < (z->y + z->h); y++)
> +                                   {
> +                                      s = src_data + (stride * y) + (z->x * 
> 4);
> +                                      memcpy(d, s, z->w * 4);
> +                                      d += z->w * 4;
> +                                   }
> +                              }
> +                         }
> +                    }
> +               }
> +          }
> +        if (data)
> +          {
> +             thdat = calloc(1, sizeof(Rgba_Writer_Data));
> +             if (thdat)
> +               {
> +                  thdat->path = strdup(path);
> +                  if (file) thdat->outfile = strdup(file);
> +                  if ((thdat->path) &&
> +                      (((file) && (thdat->outfile)) ||
> +                       (!file)))
> +                    {
> +                       thdat->data = data;
> +                       thdat->size = size;
> +                       thdat->fd = fd;
> +                       thdat->w = imw;
> +                       thdat->h = imh;
> +                       thdat->stride = imstride;
> +                       thdat->quality = quality;
> +                       ecore_thread_run(_cb_rgba_writer_do,
> +                                        _cb_rgba_writer_done,
> +                                        _cb_rgba_writer_cancel, thdat);
> +                    }
> +                  else
> +                    {
> +                       free(thdat->path);
> +                       free(thdat->outfile);
> +                       free(thdat);
> +                       thdat = NULL;
> +                    }
> +               }
> +             else
> +               {
> +                  close(fd);
> +                  free(data);
> +               }
> +          }
> +        if (!thdat) close(fd);
> +        eina_tmpstr_del(path);
> +     }
> +   return;
> +}
> +
> +static void
> +_file_select_ok_cb(void *data EINA_UNUSED, E_Dialog *dia)
> +{
> +   const char *file;
> +
> +   dia = fsel_dia;
> +   file = e_widget_fsel_selection_path_get(o_fsel);
> +   if ((!file) || (!file[0]) ||
> +       ((!eina_str_has_extension(file, ".jpg")) &&
> +        (!eina_str_has_extension(file, ".png"))))
> +     {
> +        e_util_dialog_show
> +        (_("Error - Unknown format"),
> +            _("File has an unspecified extension.<ps/>"
> +              "Please use '.jpg' or '.png' extensions<ps/>"
> +              "only as other formats are not<ps/>"
> +              "supported currently."));
> +        return;
> +     }
> +   save_to(file);
> +   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> +   preview_abort();
> +   fsel_dia = NULL;
> +}
> +
> +static void
> +_file_select_cancel_cb(void *data EINA_UNUSED, E_Dialog *dia)
> +{
> +   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> +   preview_abort();
> +   fsel_dia = NULL;
> +}
> +
> +static void
> +_file_select_del_cb(void *d EINA_UNUSED)
> +{
> +   preview_abort();
> +   fsel_dia = NULL;
> +}
> +
> +void
> +save_dialog_show(void)
> +{
> +   E_Dialog *dia;
> +   Evas_Object *o;
> +   Evas_Coord mw, mh;
> +   time_t tt;
> +   struct tm *tm;
> +   char buf[PATH_MAX];
> +
> +   time(&tt);
> +   tm = localtime(&tt);
> +   if (quality == 100)
> +     strftime(buf, sizeof(buf), "shot-%Y-%m-%d_%H-%M-%S.png", tm);
> +   else
> +     strftime(buf, sizeof(buf), "shot-%Y-%m-%d_%H-%M-%S.jpg", tm);
> +   fsel_dia = dia = e_dialog_new(NULL, "E", "_e_shot_fsel");
> +   e_dialog_resizable_set(dia, EINA_TRUE);
> +   e_dialog_title_set(dia, _("Select screenshot save location"));
> +   o = e_widget_fsel_add(evas_object_evas_get(dia->win), "desktop", "/",
> +                         buf, NULL, NULL, NULL, NULL, NULL, 1);
> +   e_object_del_attach_func_set(E_OBJECT(dia), _file_select_del_cb);
> +   e_widget_fsel_window_set(o, dia->win);
> +   o_fsel = o;
> +   evas_object_show(o);
> +   e_widget_size_min_get(o, &mw, &mh);
> +   e_dialog_content_set(dia, o, mw, mh);
> +   e_dialog_button_add(dia, _("Save"), NULL,
> +                       _file_select_ok_cb, NULL);
> +   e_dialog_button_add(dia, _("Cancel"), NULL,
> +                       _file_select_cancel_cb, NULL);
> +   elm_win_center(dia->win, 1, 1);
> +   o = evas_object_rectangle_add(evas_object_evas_get(dia->win));
> +   e_dialog_show(dia);
> +}
> +
> +Eina_Bool
> +save_have(void)
> +{
> +   if (fsel_dia) return EINA_TRUE;
> +   return EINA_FALSE;
> +}
> +
> +void
> +save_abort(void)
> +{
> +   E_FREE_FUNC(fsel_dia, e_object_del);
> +}
> diff --git a/src/modules/shot/e_mod_share.c b/src/modules/shot/e_mod_share.c
> new file mode 100644
> index 000000000..2024f7fc9
> --- /dev/null
> +++ b/src/modules/shot/e_mod_share.c
> @@ -0,0 +1,217 @@
> +#include "e_mod_main.h"
> +
> +static Evas_Object      *win = NULL;
> +static E_Confirm_Dialog *cd = NULL;
> +static Ecore_Exe        *img_write_exe = NULL;
> +static Evas_Object      *o_label = NULL;
> +static Evas_Object      *o_entry = NULL;
> +static Eina_List        *handlers = NULL;
> +static char             *url_ret = NULL;
> +
> +// clean up and be done
> +static void
> +_share_done(void)
> +{
> +   E_FREE_LIST(handlers, ecore_event_handler_del);
> +   free(url_ret);
> +   o_label = NULL;
> +   img_write_exe = NULL;
> +   url_ret = NULL;
> +   preview_abort();
> +}
> +
> +// the upload dialog
> +static void
> +_upload_ok_cb(void *data EINA_UNUSED, E_Dialog *dia)
> +{
> +   // ok just hides dialog and does background upload
> +   o_label = NULL;
> +   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> +   if (!win) return;
> +   E_FREE_FUNC(win, evas_object_del);
> +}
> +
> +static void
> +_upload_cancel_cb(void *data EINA_UNUSED, E_Dialog *dia)
> +{
> +   o_label = NULL;
> +   if (dia) e_util_defer_object_del(E_OBJECT(dia));
> +   E_FREE_FUNC(win, evas_object_del);
> +   _share_done();
> +}
> +
> +static Eina_Bool
> +_img_write_end_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void 
> *event)
> +{
> +   Ecore_Exe_Event_Del *ev = event;
> +
> +   if (ev->exe != img_write_exe) return EINA_TRUE;
> +   _share_done();
> +   return EINA_FALSE;
> +}
> +
> +static Eina_Bool
> +_img_write_out_cb(void *data, int ev_type EINA_UNUSED, void *event)
> +{
> +   Ecore_Exe_Event_Data *ev = event;
> +   int i;
> +
> +   if (ev->exe != img_write_exe) return EINA_TRUE;
> +   if (!((ev->lines) && (ev->lines[0].line))) goto done;
> +   for (i = 0; ev->lines[i].line; i++)
> +     {
> +        const char *l = ev->lines[i].line;
> +
> +        if ((l[0] == 'U') && (l[1] == ' '))
> +          {
> +             int v = atoi(l + 2);
> +             if ((v >= 0) && (v <= 1000))
> +               {
> +                  char buf[128];
> +                  // update gui...
> +                  snprintf(buf, sizeof(buf), _("Uploaded %i%%"), (v * 100) / 
> 1000);
> +                  e_widget_label_text_set(o_label, buf);
> +               }
> +          }
> +        else if ((l[0] == 'R') && (l[1] == ' '))
> +          {
> +             const char *r = l + 2;
> +             // finished - got final url
> +             if (!url_ret) url_ret = strdup(r);
> +          }
> +        else if ((l[0] == 'E') && (l[1] == ' '))
> +          {
> +             int err = atoi(l + 2);
> +             if (data) e_widget_disabled_set(data, 1);
> +             e_util_dialog_show(_("Error - Upload Failed"),
> +                                _("Upload failed with status code:<ps/>%i"),
> +                                err);
> +             _share_done();
> +             break;
> +          }
> +        else if ((l[0] == 'O'))
> +          {
> +             if (data) e_widget_disabled_set(data, 1);
> +             if ((o_entry) && (url_ret))
> +             e_widget_entry_text_set(o_entry, url_ret);
> +             _share_done();
> +             break;
> +          }
> +     }
> +done:
> +   return EINA_FALSE;
> +}
> +
> +void
> +share_save(const char *cmd)
> +{
> +   share_write_end_watch(NULL);
> +   img_write_exe = ecore_exe_pipe_run
> +     (cmd, ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_READ_LINE_BUFFERED |
> +      ECORE_EXE_NOT_LEADER | ECORE_EXE_TERM_WITH_PARENT, NULL);
> +}
> +
> +void
> +share_write_end_watch(void *data)
> +{
> +   E_LIST_HANDLER_APPEND(handlers, ECORE_EXE_EVENT_DEL,
> +                         _img_write_end_cb, data);
> +}
> +
> +void
> +share_write_status_watch(void *data)
> +{
> +   E_LIST_HANDLER_APPEND(handlers, ECORE_EXE_EVENT_DATA,
> +                         _img_write_out_cb, data);
> +}
> +
> +static void
> +_win_share_del(void *data EINA_UNUSED)
> +{
> +   if (handlers)
> +     ecore_event_handler_data_set(eina_list_last_data_get(handlers), NULL);
> +   _upload_cancel_cb(NULL, NULL);
> +   if (cd) e_object_del(E_OBJECT(cd));
> +}
> +
> +void
> +share_dialog_show(void)
> +{
> +   E_Dialog *dia;
> +   Evas_Object *o, *ol;
> +   Evas_Coord mw, mh;
> +
> +   E_FREE_LIST(handlers, ecore_event_handler_del);
> +
> +   save_to(NULL);
> +
> +   E_FREE_FUNC(win, evas_object_del);
> +
> +   dia = e_dialog_new(NULL, "E", "_e_shot_share");
> +   e_dialog_resizable_set(dia, EINA_TRUE);
> +   e_dialog_title_set(dia, _("Uploading screenshot"));
> +
> +   o = e_widget_list_add(evas_object_evas_get(dia->win), 0, 0);
> +   ol = o;
> +
> +   o = e_widget_label_add(evas_object_evas_get(dia->win), _("Uploading 
> ..."));
> +   o_label = o;
> +   e_widget_list_object_append(ol, o, 0, 0, 0.5);
> +
> +   o = e_widget_label_add(evas_object_evas_get(dia->win),
> +                          _("Screenshot is available at this location:"));
> +   e_widget_list_object_append(ol, o, 0, 0, 0.5);
> +
> +   o = e_widget_entry_add(dia->win, NULL, NULL, NULL, NULL);
> +   o_entry = o;
> +   e_widget_list_object_append(ol, o, 1, 0, 0.5);
> +
> +   e_widget_size_min_get(ol, &mw, &mh);
> +   e_dialog_content_set(dia, ol, mw, mh);
> +   e_dialog_button_add(dia, _("Hide"), NULL, _upload_ok_cb, NULL);
> +   e_dialog_button_add(dia, _("Cancel"), NULL, _upload_cancel_cb, NULL);
> +   e_object_del_attach_func_set(E_OBJECT(dia), _win_share_del);
> +   share_write_status_watch(eina_list_last_data_get(dia->buttons));
> +   elm_win_center(dia->win, 1, 1);
> +   e_dialog_show(dia);
> +}
> +
> +// confirm dialog that it's ok to share
> +static void
> +_win_share_confirm_del(void *d EINA_UNUSED)
> +{
> +   cd = NULL;
> +}
> +
> +static void
> +_win_share_confirm_yes(void *d EINA_UNUSED)
> +{
> +   share_dialog_show();
> +}
> +
> +void
> +share_confirm(void)
> +{
> +   if (cd) return;
> +   cd = e_confirm_dialog_show
> +     (_("Confirm Share"), NULL,
> +      _("This image will be uploaded<ps/>"
> +        "to enlightenment.org. It will be publicly visible."),
> +      _("Confirm"), _("Cancel"),
> +      _win_share_confirm_yes, NULL,
> +      NULL, NULL, _win_share_confirm_del, NULL);
> +}
> +
> +Eina_Bool
> +share_have(void)
> +{
> +   if (img_write_exe) return EINA_TRUE;
> +   return EINA_FALSE;
> +}
> +
> +void
> +share_abort(void)
> +{
> +   E_FREE_FUNC(cd, e_object_del);
> +   E_FREE_FUNC(win, evas_object_del);
> +}
> diff --git a/src/modules/shot/meson.build b/src/modules/shot/meson.build
> index 42119f40e..132fc98a3 100644
> --- a/src/modules/shot/meson.build
> +++ b/src/modules/shot/meson.build
> @@ -1,3 +1,17 @@
>   src = files(
> -  'e_mod_main.c'
> - )
> +  'e_mod_main.c',
> +  'e_mod_main.h',
> +  'e_mod_preview.c',
> +  'e_mod_save.c',
> +  'e_mod_share.c'
> +)
> +
> +if get_option(m) == true
> +  executable('upload',
> +             'upload.c',
> +             include_directories: include_directories(module_includes),
> +             dependencies       : [ dep_elementary ],
> +             install_dir        : _dir_bin,
> +             install            : true
> +            )
> +endif
> diff --git a/src/modules/shot/upload.c b/src/modules/shot/upload.c
> new file mode 100644
> index 000000000..b7236a30c
> --- /dev/null
> +++ b/src/modules/shot/upload.c
> @@ -0,0 +1,208 @@
> +#include <Elementary.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +
> +static Ecore_Con_Url *url_up = NULL;
> +
> +static Eina_Bool
> +_upload_data_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
> +{
> +   Ecore_Con_Event_Url_Data *ev = event;
> +
> +   if (ev->url_con != url_up) return EINA_TRUE;
> +   if (ev->size < 1024)
> +     {
> +        char *txt = alloca(ev->size + 1);
> +
> +        memcpy(txt, ev->data, ev->size);
> +        txt[ev->size] = 0;
> +        printf("R %s\n", txt);
> +        fflush(stdout);
> +     }
> +   return EINA_FALSE;
> +}
> +
> +static Eina_Bool
> +_upload_progress_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void 
> *event)
> +{
> +   size_t total, current;
> +   Ecore_Con_Event_Url_Progress *ev = event;
> +
> +   if (ev->url_con != url_up) return EINA_TRUE;
> +   total = ev->up.total;
> +   current = ev->up.now;
> +   if (total > 0)
> +     {
> +        printf("U %i\n", (int)((current * 1000) / total));
> +        fflush(stdout);
> +     }
> +   return EINA_FALSE;
> +}
> +
> +static Eina_Bool
> +_upload_complete_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void 
> *event)
> +{
> +   Ecore_Con_Event_Url_Complete *ev = event;
> +
> +   if (ev->url_con != url_up) return EINA_TRUE;
> +   if (ev->status != 200) printf("E %i\n", ev->status);
> +   else printf("O\n");
> +   fflush(stdout);
> +   elm_exit();
> +   return EINA_FALSE;
> +}
> +
> +static Eina_Bool
> +find_tmpfile(int quality, char *buf, size_t buf_size)
> +{
> +   int i;
> +
> +   // come up with a tmp file - not really that critical as its due for
> +   // sharing to the internet as a whole
> +   srand(time(NULL));
> +   for (i = 0; i < 100; i++)
> +     {
> +        int fd, v = rand();
> +
> +        if (quality == 100) snprintf(buf, buf_size, "/tmp/e-shot-%x.png", v);
> +        else snprintf(buf, buf_size, "/tmp/e-shot-%x.jpg", v);
> +        fd = open(buf, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
> +        if (fd >= 0)
> +          {
> +             close(fd);
> +             return EINA_TRUE;
> +          }
> +        close(fd);
> +     }
> +   return EINA_FALSE;
> +}
> +
> +EAPI int
> +elm_main(int argc, char **argv)
> +{
> +   Evas_Object *win, *image;
> +   Eina_File *infile;
> +   void *fdata;
> +   size_t fsize;
> +   Eina_Bool upload = EINA_FALSE;
> +   const char *rgba_file, *out_file = NULL;
> +   int w, h, stride, quality, image_stride, y;
> +   char *image_data, *src;
> +   char opts[256];
> +
> +   if (argc < 6) return 1;
> +
> +   rgba_file = argv[1]; // path to raw linear memory format rgba32 pixel data
> +   w         = atoi(argv[2]); // width in pixels
> +   h         = atoi(argv[3]); // height in pixels
> +   stride    = atoi(argv[4]); // stride per line in bytes
> +   quality   = atoi(argv[5]); // qwuality to save out as (100 == lossless 
> png)
> +   if (argc >= 7) out_file = eina_stringshare_add(argv[6]); // out file path
> +
> +   // set up buffer window as scratch space
> +   elm_config_preferred_engine_set("buffer");
> +   win = elm_win_add(NULL, "Shot-Upload", ELM_WIN_BASIC);
> +   elm_win_norender_push(win);
> +
> +   // come up with tmp out file if no dest out provided
> +   if (!out_file)
> +     {
> +        char buf[PATH_MAX];
> +
> +        upload = EINA_TRUE;
> +        if (find_tmpfile(quality, buf, sizeof(buf)))
> +          out_file = eina_stringshare_add(buf);
> +     }
> +   // open raw rgba data file which we willl mmap
> +   infile = eina_file_open(rgba_file, EINA_FALSE);
> +   if (!infile) return 2;
> +   fsize = eina_file_size_get(infile);
> +   fdata = eina_file_map_all(infile, EINA_FILE_SEQUENTIAL);
> +   if (!((fsize > 0) && (fdata)))
> +     {
> +        ecore_file_unlink(rgba_file);
> +        return 3;
> +     }
> +
> +   // create image objectfor saving out with right format and size
> +   image = evas_object_image_add(evas_object_evas_get(win));
> +   evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
> +   evas_object_image_alpha_set(image, EINA_FALSE);
> +   evas_object_image_size_set(image, w, h);
> +   image_stride = evas_object_image_stride_get(image);
> +   image_data = evas_object_image_data_get(image, EINA_TRUE);
> +   if (!((image_stride > 0) && (image_data)))
> +     {
> +        ecore_file_unlink(rgba_file);
> +        return 4;
> +     }
> +   // copy data into output image (could also set data straight in
> +   src = fdata;
> +   for (y = 0; y < h; y++)
> +     {
> +        memcpy(image_data, src, w * 4);
> +        image_data += image_stride;
> +        src += stride;
> +     }
> +   if (quality == 100)
> +     snprintf(opts, sizeof(opts), "compress=%i", 9);
> +   else
> +     snprintf(opts, sizeof(opts), "quality=%i", quality);
> +   eina_file_close(infile);
> +   ecore_file_unlink(rgba_file);
> +   // save the file
> +   if (!evas_object_image_save(image, out_file, NULL, opts))
> +     return 5;
> +
> +   // if we have to upload it, open our output file, mmap it and upload
> +   if (upload)
> +     {
> +        infile = eina_file_open(out_file, EINA_FALSE);
> +        if (infile)
> +          {
> +             fsize = eina_file_size_get(infile);
> +             fdata = eina_file_map_all(infile, EINA_FILE_SEQUENTIAL);
> +             if ((fsize > 0) && (fdata))
> +               {
> +                  Ecore_Event_Handler *h1, *h2, *h3;
> +
> +                  h1 = ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA,
> +                                               _upload_data_cb, NULL);
> +                  h2 = ecore_event_handler_add(ECORE_CON_EVENT_URL_PROGRESS,
> +                                               _upload_progress_cb, NULL);
> +                  h3 = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE,
> +                                               _upload_complete_cb, NULL);
> +                  if ((h1) && (h2) && (h3))
> +                    {
> +                       url_up = ecore_con_url_new
> +                         
> ("https://protect2.fireeye.com/url?k=b9adc0a4-e463c177-b9ac4beb-000babff317b-06320a5be253eae2&u=https://www.enlightenment.org/shot.php";);
> +                       if (url_up)
> +                         {
> +                            // why use http 1.1? proxies like squid don't
> +                            // handle 1.1 posts with expect like curl uses
> +                            // by default, so go to 1.0 and this all works
> +                            // dandily out of the box
> +                            ecore_con_url_http_version_set
> +                              (url_up, ECORE_CON_URL_HTTP_VERSION_1_0);
> +                            ecore_con_url_post
> +                              (url_up, fdata, fsize, "application/x-e-shot");
> +                            // need loop to run to drive the uploading
> +                            elm_run();
> +                         }
> +                    }
> +                  ecore_event_handler_del(h1);
> +                  ecore_event_handler_del(h2);
> +                  ecore_event_handler_del(h3);
> +               }
> +             if (fdata) eina_file_map_free(infile, fdata);
> +             eina_file_close(infile);
> +          }
> +        // output was temporary here
> +        ecore_file_unlink(out_file);
> +     }
> +   evas_object_del(win);
> +   eina_stringshare_del(out_file);
> +   return 0;
> +}
> +ELM_MAIN()
> 


_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to