On Thu, 19 Dec 2019 19:58:54 -0500 Christopher Michael <cp.mich...@samsung.com>
said:

implementing crop is easy. i'm more thinking about perhaps changing from a
window to a fullscreen image so you crop/edit a still "in-place" - at least for
fullscreen shots... then overlaying the tools (crop will be one of them along
with a blur region, draw line, outline box, solid rect, draw arrow line, and
some text notes - choosing various colors and styles for these). so cropping is
actually a tiny amount of what's on the todo...

> 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
> 


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
Carsten Haitzler - ras...@rasterman.com



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

Reply via email to