discomfitor pushed a commit to branch master.

http://git.enlightenment.org/enlightenment/modules/desksanity.git/commit/?id=ca2e4eb738f03bdae2e05efe54fbd8d0161e5d54

commit ca2e4eb738f03bdae2e05efe54fbd8d0161e5d54
Author: Mike Blumenkrantz <[email protected]>
Date:   Thu Jun 22 17:29:46 2017 -0400

    add runner gadget for testing
    
    runner is a desktop-only gadget which allows the running of commands
    inside a nested wayland compositor inside a gadget using hw accel where
    available
    
    it should be possible to use this for things like:
    
    * playing a movie on the desktop
    * tailing a log in a terminal
    * keeping an always-open terminal on your desktop
    * using an external filemanager on the desktop
    
    known issues:
    - do not attempt to move the gadget once placed or bad things will happen
    - some focus issues with gadget config
---
 configure.ac     |  10 +-
 src/Makefile.mk  |   4 +
 src/e_mod_main.c |  10 +-
 src/e_mod_main.h |   6 +
 src/runner.c     | 419 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 447 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 264c021..c6c8df8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,7 +30,15 @@ AC_PROG_LIBTOOL
 #])
 #AC_SUBST(LTLIBINTL)
 
-PKG_CHECK_MODULES([E], [enlightenment >= 0.21.0])
+PKG_CHECK_EXISTS([efl-wl], [build_runner="yes"], [build_runner="no"])
+
+if test "x$build_runner" = "xyes" ; then
+  runner="efl-wl"
+  AC_DEFINE_UNQUOTED(HAVE_RUNNER, 1, "have runner deps")
+fi
+AM_CONDITIONAL([BUILD_RUNNER], [test "x${build_runner}" = "xyes"])
+
+PKG_CHECK_MODULES([E], [enlightenment >= 0.21.0 $runner])
 release=$(pkg-config --variable=release enlightenment)
 MODULE_ARCH="$host_os-$host_cpu-$release"
 AC_SUBST(MODULE_ARCH)
diff --git a/src/Makefile.mk b/src/Makefile.mk
index 1649c6b..6559e64 100644
--- a/src/Makefile.mk
+++ b/src/Makefile.mk
@@ -19,6 +19,10 @@ src/zoom.c \
 src/magnify.c \
 src/desksanity.c
 
+if BUILD_RUNNER
+module_la_SOURCES += src/runner.c
+endif
+
 module_la_LIBADD = @E_LIBS@
 module_la_LDFLAGS = -module -avoid-version
 module_la_DEPENDENCIES = $(top_builddir)/config.h
diff --git a/src/e_mod_main.c b/src/e_mod_main.c
index 8ffb850..1572d40 100644
--- a/src/e_mod_main.c
+++ b/src/e_mod_main.c
@@ -261,7 +261,9 @@ e_modapi_init(E_Module *m)
    pip_init();
    zoom_init();
    mag_init();
-
+#ifdef HAVE_RUNNER
+   runner_init();
+#endif
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY, ds_client_urgent, 
NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, ds_client_remove, 
NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_AFTER_SHOW, 
ds_desk_after_show, NULL);
@@ -276,6 +278,9 @@ e_modapi_init(E_Module *m)
 E_API int
 e_modapi_shutdown(E_Module *m EINA_UNUSED)
 {
+#ifdef HAVE_RUNNER
+   runner_shutdown();
+#endif
    mag_shutdown();
    zoom_shutdown();
    pip_shutdown();
@@ -308,6 +313,9 @@ E_API int
 e_modapi_save(E_Module *m EINA_UNUSED)
 {
    e_config_domain_save("module.desksanity", conf_edd, ds_config);
+#ifdef HAVE_RUNNER
+   runner_save();
+#endif
    return 1;
 }
 
diff --git a/src/e_mod_main.h b/src/e_mod_main.h
index 0595899..0c2904d 100644
--- a/src/e_mod_main.h
+++ b/src/e_mod_main.h
@@ -105,4 +105,10 @@ EINTERN void zoom_shutdown(void);
 
 EINTERN void mag_init(void);
 EINTERN void mag_shutdown(void);
+
+#ifdef HAVE_RUNNER
+EINTERN void runner_init(void);
+EINTERN void runner_shutdown(void);
+EINTERN void runner_save(void);
+#endif
 #endif
diff --git a/src/runner.c b/src/runner.c
new file mode 100644
index 0000000..3e07219
--- /dev/null
+++ b/src/runner.c
@@ -0,0 +1,419 @@
+#include "e_mod_main.h"
+#include <Efl_Wl.h>
+
+typedef enum
+{
+   EXIT_MODE_RESTART,
+   EXIT_MODE_DELETE,
+} Exit_Mode;
+
+typedef struct Config_Item
+{
+   int id;
+   int exit_mode;
+   Eina_Bool allow_events;
+   Eina_Stringshare *cmd;
+   void *inst;
+   Eina_Bool cmd_changed : 1;
+} Config_Item;
+
+typedef struct Instance
+{
+   Evas_Object *obj;
+   Ecore_Exe *exe;
+   Config_Item *ci;
+} Instance;
+
+typedef struct RConfig
+{
+   Eina_List *items;
+   Evas_Object *config_dialog;
+} RConfig;
+
+static E_Config_DD *conf_edd = NULL;
+static E_Config_DD *conf_item_edd = NULL;
+
+static RConfig *rconfig;
+static Eina_List *instances;
+
+static Ecore_Event_Handler *exit_handler;
+
+typedef struct Wizard_Item
+{
+   E_Gadget_Wizard_End_Cb cb;
+   void *data;
+   int id;
+} Wizard_Item;
+
+static void
+_config_close(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void 
*event_info EINA_UNUSED)
+{
+   Config_Item *ci = data;
+   Instance *inst = ci->inst;
+
+   e_comp_ungrab_input(1, 1);
+   rconfig->config_dialog = NULL;
+   if (ci->cmd_changed)
+     {
+        eina_stringshare_replace(&ci->cmd, 
elm_entry_entry_get(evas_object_data_get(obj, "entry")));
+        e_config_save_queue();
+     }
+   if (!inst) ci->cmd_changed = 0;
+   if (!ci->cmd_changed) return;
+   ci->cmd_changed = 0;
+   if (inst->exe) ecore_exe_quit(inst->exe);
+   inst->exe = efl_wl_run(inst->obj, inst->ci->cmd);
+}
+
+static void
+_config_label_add(Evas_Object *tb, const char *txt, int row)
+{
+   Evas_Object *o;
+
+   o = elm_label_add(tb);
+   E_ALIGN(o, 0, 0.5);
+   elm_object_text_set(o, txt);
+   evas_object_show(o);
+   elm_table_pack(tb, o, 0, row, 1, 1);
+}
+
+static void
+_config_events_changed(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   Config_Item *ci = data;
+   Instance *inst = ci->inst;
+
+   if (inst)
+     evas_object_pass_events_set(inst->obj, !ci->allow_events);
+   e_config_save_queue();
+}
+
+static void
+_config_cmd_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info 
EINA_UNUSED)
+{
+   Config_Item *ci = data;
+
+   ci->cmd_changed = 1;
+}
+
+static void
+_config_cmd_activate(void *data, Evas_Object *obj, void *event_info 
EINA_UNUSED)
+{
+   Config_Item *ci = data;
+   Instance *inst = ci->inst;
+
+   ci->cmd_changed = 0;
+   eina_stringshare_replace(&ci->cmd, elm_entry_entry_get(obj));
+   e_config_save_queue();
+   if (!inst) return;
+   if (inst->exe) ecore_exe_quit(inst->exe);
+   inst->exe = efl_wl_run(inst->obj, inst->ci->cmd);
+}
+
+EINTERN Evas_Object *
+config_runner(Config_Item *ci, E_Zone *zone)
+{
+   Evas_Object *popup, *tb, *o, *ent, *rg;
+   int row = 0;
+
+   if (!zone) zone = e_zone_current_get();
+   popup = elm_popup_add(e_comp->elm);
+   E_EXPAND(popup);
+   evas_object_layer_set(popup, E_LAYER_POPUP);
+   elm_popup_allow_events_set(popup, 1);
+   elm_popup_scrollable_set(popup, 1);
+
+   tb = elm_table_add(popup);
+   elm_table_align_set(tb, 0, 0.5);
+   E_EXPAND(tb);
+   evas_object_show(tb);
+   elm_object_content_set(popup, tb);
+
+   o = evas_object_rectangle_add(e_comp->evas);
+   evas_object_size_hint_min_set(o, ELM_SCALE_SIZE(200), 1);
+   elm_table_pack(tb, o, 0, row++, 2, 1);
+
+   _config_label_add(tb, D_("Command:"), row);
+   ent = o = elm_entry_add(tb);
+   E_FILL(o);
+   evas_object_show(o);
+   elm_entry_single_line_set(o, 1);
+   elm_object_focus_set(o, 1);
+   elm_entry_entry_set(o, ci->cmd);
+   evas_object_smart_callback_add(o, "changed,user", _config_cmd_changed, ci);
+   evas_object_smart_callback_add(o, "activated", _config_cmd_activate, ci);
+   elm_table_pack(tb, o, 1, row++, 1, 1);
+
+   _config_label_add(tb, D_("On Exit:"), row);
+   o = rg = elm_radio_add(tb);
+   E_FILL(o);
+   evas_object_show(o);
+   elm_object_text_set(o, D_("Restart"));
+   elm_radio_state_value_set(o, EXIT_MODE_RESTART);
+   elm_radio_value_pointer_set(o, &ci->exit_mode);
+   elm_table_pack(tb, o, 1, row++, 1, 1);
+
+   o = elm_radio_add(tb);
+   E_FILL(o);
+   elm_radio_group_add(o, rg);
+   evas_object_show(o);
+   elm_object_text_set(o, D_("Delete"));
+   elm_radio_state_value_set(o, EXIT_MODE_DELETE);
+   elm_table_pack(tb, o, 1, row++, 1, 1);
+
+   _config_label_add(tb, D_("Allow events"), row);
+   o = elm_check_add(tb);
+   E_FILL(o);
+   evas_object_show(o);
+   elm_object_style_set(o, "toggle");
+   elm_object_part_text_set(o, "on", D_("Yes"));
+   elm_object_part_text_set(o, "off", D_("No"));
+   elm_check_state_pointer_set(o, &ci->allow_events);
+   evas_object_smart_callback_add(o, "changed", _config_events_changed, ci);
+   evas_object_data_set(o, "table", tb);
+   elm_table_pack(tb, o, 1, row++, 1, 1);
+
+   popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE);
+   evas_object_layer_set(popup, E_LAYER_POPUP);
+   evas_object_move(popup, zone->x, zone->y);
+   evas_object_resize(popup, zone->w / 4, zone->h / 3);
+   e_comp_object_util_center(popup);
+   evas_object_show(popup);
+   e_comp_object_util_autoclose(popup, NULL, 
e_comp_object_util_autoclose_on_escape, NULL);
+   evas_object_event_callback_priority_add(popup, EVAS_CALLBACK_DEL, 
EVAS_CALLBACK_PRIORITY_BEFORE, _config_close, ci);
+   evas_object_data_set(popup, "entry", ent);
+   e_comp_grab_input(1, 1);
+
+   return rconfig->config_dialog = popup;
+}
+
+static Config_Item *
+_conf_item_get(int *id)
+{
+   Config_Item *ci;
+   Eina_List *l;
+
+   if (*id > 0)
+     {
+        EINA_LIST_FOREACH(rconfig->items, l, ci)
+          if (*id == ci->id) return ci;
+     }
+
+   ci = E_NEW(Config_Item, 1);
+   if (!*id)
+     ci->id = rconfig->items ? eina_list_count(rconfig->items) + 1 : 1;
+   else
+     ci->id = -1;
+
+   ci->allow_events = 0;
+
+   if (ci->id < 1) return ci;
+   rconfig->items = eina_list_append(rconfig->items, ci);
+   e_config_save_queue();
+
+   return ci;
+}
+
+static void
+_wizard_end(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+{
+   Wizard_Item *wi = data;
+   Eina_List *l;
+   Config_Item *ci;
+
+   EINA_LIST_FOREACH(rconfig->items, l, ci)
+     {
+        if (ci->id == wi->id)
+          {
+             if (ci->cmd) break;
+             wi->id = 0;
+             free(ci);
+             rconfig->items = eina_list_remove_list(rconfig->items, l);
+             break;
+          }
+     }
+
+   wi->cb(wi->data, wi->id);
+   free(wi);
+}
+
+static Evas_Object *
+runner_wizard(E_Gadget_Wizard_End_Cb cb, void *data)
+{
+   int id = 0;
+   Config_Item *ci;
+   Wizard_Item *wi;
+   Evas_Object *obj;
+
+   wi = E_NEW(Wizard_Item, 1);
+   wi->cb = cb;
+   wi->data = data;
+
+   ci = _conf_item_get(&id);
+   wi->id = ci->id;
+   obj = config_runner(ci, NULL);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _wizard_end, wi);
+   return obj;
+}
+
+/////////////////////////////////////////
+
+static void
+mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   Instance *inst = data;
+   evas_object_focus_set(inst->obj, 1);
+}
+
+static void
+runner_removed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Instance *inst = data;
+   if (inst->obj != event_info) return;
+   rconfig->items = eina_list_remove(rconfig->items, inst->ci);
+   eina_stringshare_del(inst->ci->cmd);
+   E_FREE(inst->ci);
+}
+
+static void
+runner_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info 
EINA_UNUSED)
+{
+   Instance *inst = data;
+
+   evas_object_smart_callback_del_full(e_gadget_site_get(obj), 
"gadget_removed", runner_removed, inst);
+   if (inst->ci) inst->ci->inst = NULL;
+   instances = eina_list_remove(instances, inst);
+   free(inst);
+}
+
+static Evas_Object *
+runner_gadget_configure(Evas_Object *g)
+{
+   Instance *inst = evas_object_data_get(g, "runner");
+   return config_runner(inst->ci, e_comp_object_util_zone_get(g));
+}
+
+static void
+runner_created(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   Instance *inst = data;
+   if (inst->obj != event_info) return;
+   e_gadget_configure_cb_set(inst->obj, runner_gadget_configure);
+   evas_object_smart_callback_del_full(obj, "gadget_created", runner_created, 
data);
+}
+
+static Evas_Object *
+runner_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
+{
+   Evas_Object *obj;
+   Instance *inst;
+   Config_Item *ci = NULL;
+
+   if (orient) return NULL;
+   if (*id > 0) ci = _conf_item_get(id);
+   if ((*id < 0) || ci->inst)
+     {
+        obj = elm_image_add(parent);
+        elm_image_file_set(obj, e_theme_edje_file_get(NULL, 
"e/icons/modules-launcher"), "e/icons/modules-launcher");
+        evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
+        return obj;
+     }
+   inst = E_NEW(Instance, 1);
+   instances = eina_list_append(instances, inst);
+   inst->ci = ci;
+   if (!inst->ci)
+     inst->ci = _conf_item_get(id);
+   inst->ci->inst = inst;
+   inst->obj = efl_wl_add(e_comp->evas);
+   evas_object_data_set(inst->obj, "runner", inst);
+   evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_MOUSE_DOWN, 
mouse_down, inst);
+   evas_object_smart_callback_add(parent, "gadget_created", runner_created, 
inst);
+   evas_object_smart_callback_add(parent, "gadget_removed", runner_removed, 
inst);
+   evas_object_pass_events_set(inst->obj, !inst->ci->allow_events);
+   inst->exe = efl_wl_run(inst->obj, inst->ci->cmd);
+   ecore_exe_data_set(inst->exe, inst);
+   evas_object_event_callback_add(inst->obj, EVAS_CALLBACK_DEL, runner_del, 
inst);
+   return inst->obj;
+}
+
+static Eina_Bool
+runner_exe_del(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Exe_Event_Del *ev)
+{
+   Instance *inst = ecore_exe_data_get(ev->exe);
+
+   if ((!inst) || (!instances) || (!eina_list_data_find(instances, inst))) 
return ECORE_CALLBACK_RENEW;
+   switch (inst->ci->exit_mode)
+     {
+      case EXIT_MODE_RESTART:
+        inst->exe = efl_wl_run(inst->obj, inst->ci->cmd);
+        ecore_exe_data_set(inst->exe, inst);
+        break;
+      case EXIT_MODE_DELETE:
+        e_gadget_del(inst->obj);
+        break;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+///////////////////////////////
+
+EINTERN void
+runner_init(void)
+{
+   conf_item_edd = E_CONFIG_DD_NEW("Config_Item", Config_Item);
+#undef T
+#undef D
+#define T Config_Item
+#define D conf_item_edd
+   E_CONFIG_VAL(D, T, id, INT);
+   E_CONFIG_VAL(D, T, allow_events, UCHAR);
+   E_CONFIG_VAL(D, T, exit_mode, INT);
+   E_CONFIG_VAL(D, T, cmd, STR);
+
+   conf_edd = E_CONFIG_DD_NEW("RConfig", RConfig);
+#undef T
+#undef D
+#define T RConfig
+#define D conf_edd
+   E_CONFIG_LIST(D, T, items, conf_item_edd);
+
+   rconfig = e_config_domain_load("module.runner", conf_edd);
+   if (!rconfig) rconfig = E_NEW(RConfig, 1);
+
+   e_gadget_type_add("runner", runner_create, runner_wizard);
+   exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, 
(Ecore_Event_Handler_Cb)runner_exe_del, NULL);
+}
+
+EINTERN void
+runner_shutdown(void)
+{
+   e_gadget_type_del("runner");
+
+   if (rconfig)
+     {
+        Config_Item *ci;
+
+        if (rconfig->config_dialog)
+          {
+             evas_object_hide(rconfig->config_dialog);
+             evas_object_del(rconfig->config_dialog);
+          }
+
+        EINA_LIST_FREE(rconfig->items, ci)
+          {
+             eina_stringshare_del(ci->cmd);
+             free(ci);
+          }
+
+     }
+   E_FREE(rconfig);
+   E_CONFIG_DD_FREE(conf_edd);
+   E_CONFIG_DD_FREE(conf_item_edd);
+   E_FREE_FUNC(exit_handler, ecore_event_handler_del);
+}
+
+EINTERN void
+runner_save(void)
+{
+   e_config_domain_save("module.runner", conf_edd, rconfig);
+}

-- 


Reply via email to