On Mon, Dec 19, 2011 at 7:54 AM, Enlightenment SVN <no-re...@enlightenment.org> wrote: > Log: > address fixme's in extn :) > > > > Author: raster > Date: 2011-12-18 22:54:08 -0800 (Sun, 18 Dec 2011) > New Revision: 66320 > Trac: http://trac.enlightenment.org/e/changeset/66320 > > Modified: > trunk/ecore/src/lib/ecore_evas/Ecore_Evas.h > trunk/ecore/src/lib/ecore_evas/ecore_evas.c > trunk/ecore/src/lib/ecore_evas/ecore_evas_extn.c > trunk/ecore/src/lib/ecore_evas/ecore_evas_private.h > > Modified: trunk/ecore/src/lib/ecore_evas/Ecore_Evas.h > =================================================================== > --- trunk/ecore/src/lib/ecore_evas/Ecore_Evas.h 2011-12-19 05:57:31 UTC (rev > 66319) > +++ trunk/ecore/src/lib/ecore_evas/Ecore_Evas.h 2011-12-19 06:54:08 UTC (rev > 66320) > @@ -1649,14 +1649,146 @@ > */ > > /** > + * @defgroup Ecore_Evas_Extn External plug/socket infrastructure to remote > canvases > + * > + * These functions allow 1 process to create a "socket" into which another > + * process can create a "plug" remotely to plug into and provide content > + * for that socket. This is best for small sized objects (about the size > range > + * of a small icon up to a few large icons). Sine the socket is actually an > + * image object, you cvan fetch the pixel data > + * > + * @since 1.2 > + * @{ > + */ > + > +EAPI extern int ECORE_EVAS_EXTN_CLIENT_ADD; /**< this event is received when > a plug has connected to an extn socket */ > +EAPI extern int ECORE_EVAS_EXTN_CLIENT_DEL; /**< this event is received when > a plug has disconnected from an extn socket */
@since 1.2 too just above Vincent > + > +/** > * Create a new external ecore evas socket > * > + * @param ee_target The Ecore_Evas containing the canvas in which the new > image object will live. > + * @param svcname The name of the service to be advertised. ensure that it > is unique (when combined with @p svcnum) otherwise creation may fail. > + * @param svcnum A number (any value, 0 beig the common default) to > differentiate multiple instances of services with the same name. > + * @param svcsys A boolean that if true, specifies to create a system-wide > service all users can connect to, otherwise the service is private to the > user ide that created the service. > + * @return An evas image object that will contain the image output of a plug > when it plugs in > + * > + * This creates an image object that will contain the output of another > + * processes plug canvas when it connects. All input will be sent back to > + * this process as well, effectively swallowing or placing the plug process > + * in the canvas of the socket process in place of the image object. The > image > + * object by default is created to be filled (equivalent of > + * evas_object_image_filled_add() on creation) so image content will scale > + * toi fill the image unless otherwise reconfigured. The Ecore_Evas size > + * of the socket is the master size and determines size in pixels of the > + * plug canvas. You can change the size with something like: > + * > + * @code > + * ecore_evas_resize(ecore_evas_object_ecore_evas_get(obj), 240, 400); > + * @endcode > + * > + * The image object begins as a blank object until a plug client connects. > + * When a client connects, you will get the ECORE_EVAS_EXTN_CLIENT_ADD event > + * in the ecore event queue, with event_info being the image object pointer > + * passed as a void pointer. When a cllient disconnects you will get the > + * ECORE_EVAS_EXTN_CLIENT_DEL event, and the image object will become blank. > + * > + * You can set up event handles for these events as follows: > + * > + * @code > + * static void client_add_cb(void *data, int event, void *event_info) > + * { > + * Evas_Object *obj = event_info; > + * printf("client added to image object %p\n", obj); > + * evas_object_show(obj); > + * } > + * > + * static void client_del_cb(void *data, int event, void *event_info) > + * { > + * Evas_Object *obj = event_info; > + * printf("client deleted from image object %p\n", obj); > + * evas_object_hide(obj); > + * } > + * > + * void setup(void) > + * { > + * ecore_event_handler_add(ECORE_EVAS_EXTN_CLIENT_ADD, > + * client_add_cb, NULL); > + * ecore_event_handler_add(ECORE_EVAS_EXTN_CLIENT_DEL, > + * client_del_cb, NULL); > + * } > + * @endcode > + * > + * Note that events come in later after the event happened. You may want to > be > + * careful as data structures you had associated with the image object > + * may have been freed after deleting, but the object may still be around > + * awating cleanup and thus still be valid. > + * > + * @see ecore_evas_extn_socket_object_data_lock() > + * @see ecore_evas_extn_socket_object_data_unlock() > + * @see ecore_evas_extn_plug_new() > + * > * @since 1.2 > */ > EAPI Evas_Object *ecore_evas_extn_socket_new(Ecore_Evas *ee_target, const > char *svcname, int svcnum, Eina_Bool svcsys); > + > /** > + * Lock the pixel data so the plug cannot change it > + * > + * @param obj The image object returned by ecore_evas_extn_socket_new() to > lock > + * > + * You may need to get the image pixel data with evas_object_image_data_get() > + * from the image object, but need to ensure that it does not change while > + * you are using the data. This function lets you set an advisory lock on the > + * image data so the external plug process will not render to it or alter it. > + * > + * You should only hold the lock for just as long as you need to read out the > + * image data or otherwise deal with it, and then unlokc it with > + * ecore_evas_extn_socket_object_data_unlock(). Keeping a lock over more than > + * 1 iteration of the main ecore loop will be problematic, so avoid it. Also > + * forgetting to unlock may cause the plug process to freeze and thus create > + * odd behavior. > + * > + * @see ecore_evas_extn_socket_new() > + * @see ecore_evas_extn_socket_object_data_unlock() > + * > + * @since 1.2 > + */ > +EAPI void ecore_evas_extn_socket_object_data_lock(Evas_Object *obj); > + > +/** > + * Unlock the pixel data so the plug can change it again. > + * > + * @param obj The image object returned by ecore_evas_extn_socket_new() to > unlock > + * > + * This unlocks after an advisor lock has been taken by > + * ecore_evas_extn_socket_object_data_lock(). > + * > + * @see ecore_evas_extn_socket_new() > + * @see ecore_evas_extn_socket_object_data_lock() > + * > + * @since 1.2 > + */ > +EAPI void ecore_evas_extn_socket_object_data_unlock(Evas_Object *obj); > + > +/** > * Create a new external ecore evas plug > * > + * @param svcname The service name to connect to set up by the socket. > + * @param svcnum The service number to connect to (set up by socket). > + * @param svcsys Booleain to set if the service is a system one or not (set > up by socket). > + * > + * This creates an Ecore_evas canvas wrapper and connects it to the given > + * socket specified by @p svcname, @p svcnum and @p svcsys. If connection > + * is successful, an Ecore_Evas handle is returned or NULL if connection > + * fails. If the socket is deleted or disconnects you for whatever reason > + * youre Ecore_Evas will get a delete request event (the delete request > + * callback will be called, if set). Also focus, show, hide etc. callbacks > + * will also be called if the socket object is shown, or already visible on > + * connect, or if it is hidden later, focused or unfocused. > + * > + * @see ecore_evas_extn_socket_new() > + * > * @since 1.2 > */ > EAPI Ecore_Evas *ecore_evas_extn_plug_new(const char *svcname, int svcnum, > Eina_Bool svcsys); > @@ -1665,6 +1797,10 @@ > * @} > */ > > +/** > + * @} > + */ > + > #ifdef __cplusplus > } > #endif > > Modified: trunk/ecore/src/lib/ecore_evas/ecore_evas.c > =================================================================== > --- trunk/ecore/src/lib/ecore_evas/ecore_evas.c 2011-12-19 05:57:31 UTC (rev > 66319) > +++ trunk/ecore/src/lib/ecore_evas/ecore_evas.c 2011-12-19 06:54:08 UTC (rev > 66320) > @@ -244,6 +244,8 @@ > _ecore_evas_ews_events_init(); > #endif > > + _ecore_evas_extn_init(); > + > if (getenv("ECORE_EVAS_COMP_NOSYNC")) > _ecore_evas_app_comp_sync = 0; > return _ecore_evas_init_count; > @@ -264,6 +266,8 @@ > > while (ecore_evases) _ecore_evas_free(ecore_evases); > > + _ecore_evas_extn_shutdown(); > + > if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown(); > ecore_idle_enterer_del(ecore_evas_idle_enterer); > ecore_evas_idle_enterer = NULL; > > Modified: trunk/ecore/src/lib/ecore_evas/ecore_evas_extn.c > =================================================================== > --- trunk/ecore/src/lib/ecore_evas/ecore_evas_extn.c 2011-12-19 05:57:31 > UTC (rev 66319) > +++ trunk/ecore/src/lib/ecore_evas/ecore_evas_extn.c 2011-12-19 06:54:08 > UTC (rev 66320) > @@ -2,10 +2,6 @@ > # include <config.h> > #endif > > -// FIXME: 1. no way to get events to know when processes connect/disconnect > -// FIXME: 2. no way to lock/unlock buffer between 2 procs (lock file but > -// no mechanism to lock/unluck around evas_render()) > - > #include <stdlib.h> > #include <unistd.h> > > @@ -35,6 +31,7 @@ > #include <sys/stat.h> > #include <fcntl.h> > #include <string.h> > +#include <sys/file.h> > > typedef struct _Shmfile Shmfile; > > @@ -151,26 +148,6 @@ > free(sf); > } > > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > // procotol version - change this as needed > #define MAJOR 0x1011 > > @@ -361,12 +338,95 @@ > int w, h; > Shmfile *shmfile; > Eina_List *updates; > + Eina_Bool have_lock : 1; > } file; > }; > > static Eina_List *extn_ee_list = NULL; > > +EAPI int ECORE_EVAS_EXTN_CLIENT_ADD = 0; > +EAPI int ECORE_EVAS_EXTN_CLIENT_DEL = 0; > + > +void > +_ecore_evas_extn_init(void) > +{ > + if (ECORE_EVAS_EXTN_CLIENT_ADD) return; > + ECORE_EVAS_EXTN_CLIENT_ADD = ecore_event_type_new(); > + ECORE_EVAS_EXTN_CLIENT_DEL = ecore_event_type_new(); > +} > + > +void > +_ecore_evas_extn_shutdown(void) > +{ > +} > + > static void > +_ecore_evas_extn_event_free(void *data, void *ev) > +{ > + Ecore_Evas *ee = data; > + if (ee->engine.buffer.image) > + evas_object_unref(ee->engine.buffer.image); > + _ecore_evas_unref(ee); > +} > + > +static void > +_ecore_evas_extn_event(Ecore_Evas *ee, int event) > +{ > + _ecore_evas_ref(ee); > + if (ee->engine.buffer.image) > + evas_object_ref(ee->engine.buffer.image); > + ecore_event_add(event, ee->engine.buffer.image, > + _ecore_evas_extn_event_free, ee); > +} > + > +static void > +_ecore_evas_socket_lock(Ecore_Evas *ee) > +{ > + Extn *extn; > + > + extn = ee->engine.buffer.data; > + if (!extn) return; > + if (extn->file.lockfd < 0) return; > + if (extn->file.have_lock) return; > + flock(extn->file.lockfd, LOCK_EX); > + extn->file.have_lock = EINA_TRUE; > +} > + > +static void > +_ecore_evas_socket_unlock(Ecore_Evas *ee) > +{ > + Extn *extn; > + > + extn = ee->engine.buffer.data; > + if (!extn) return; > + if (extn->file.lockfd < 0) return; > + if (!extn->file.have_lock) return; > + flock(extn->file.lockfd, LOCK_UN); > + extn->file.have_lock = EINA_FALSE; > +} > + > +static void > +_ecore_evas_extn_socket_targer_render_pre(void *data, Evas *e __UNUSED__, > void *event_info __UNUSED__) > +{ > + Ecore_Evas *ee = data; > + if (ee) _ecore_evas_socket_lock(ee); > +} > + > +static void > +_ecore_evas_extn_socket_targer_render_post(void *data, Evas *e __UNUSED__, > void *event_info __UNUSED__) > +{ > + Ecore_Evas *ee = data; > + if (ee) _ecore_evas_socket_unlock(ee); > +} > + > +static void > +_ecore_evas_extn_socket_image_obj_del(void *data, Evas *e __UNUSED__, > Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) > +{ > + Ecore_Evas *ee = data; > + if (ee) ecore_evas_free(ee); > +} > + > +static void > _ecore_evas_extn_coord_translate(Ecore_Evas *ee, Evas_Coord *x, Evas_Coord > *y) > { > Evas_Coord xx, yy, ww, hh, fx, fy, fw, fh; > @@ -414,6 +474,8 @@ > { > Ecore_Event_Handler *hdl; > > + if (extn->file.have_lock) > + _ecore_evas_socket_unlock(ee); > if (extn->file.lockfd) > { > close(extn->file.lockfd); > @@ -444,25 +506,28 @@ > { > Ecore_Evas *ee2; > > + evas_object_event_callback_del_full(ee->engine.buffer.image, > + EVAS_CALLBACK_DEL, > + > _ecore_evas_extn_socket_image_obj_del, > + ee); > + > evas_event_callback_del_full(evas_object_evas_get(ee->engine.buffer.image), > + EVAS_CALLBACK_RENDER_PRE, > + > _ecore_evas_extn_socket_targer_render_pre, > + ee); > + > evas_event_callback_del_full(evas_object_evas_get(ee->engine.buffer.image), > + EVAS_CALLBACK_RENDER_POST, > + > _ecore_evas_extn_socket_targer_render_post, > + ee); > + evas_object_del(ee->engine.buffer.image); > ee2 = evas_object_data_get(ee->engine.buffer.image, > "Ecore_Evas_Parent"); > - evas_object_del(ee->engine.buffer.image); > - ee2->sub_ecore_evas = eina_list_remove(ee2->sub_ecore_evas, ee); > + if (ee2) > + { > + ee2->sub_ecore_evas = eina_list_remove(ee2->sub_ecore_evas, ee); > + } > } > extn_ee_list = eina_list_remove(extn_ee_list, ee); > } > > - > - > - > - > - > - > - > - > - > - > - > - > static void > _ecore_evas_resize(Ecore_Evas *ee, int w, int h) > { > @@ -1039,18 +1104,21 @@ > Ecore_Evas *ee = data; > Extn *extn; > > - printf("client add\n"); > if (ee != > ecore_ipc_server_data_get(ecore_ipc_client_server_get(e->client))) > return ECORE_CALLBACK_PASS_ON; > if (!eina_list_data_find(extn_ee_list, ee)) > return ECORE_CALLBACK_PASS_ON; > extn = ee->engine.buffer.data; > if (!extn) return ECORE_CALLBACK_PASS_ON; > - if (extn->ipc.client) return ECORE_CALLBACK_PASS_ON; > - printf(" new cl = %p, old = %p\n", e->client, extn->ipc.client); > + if (extn->ipc.client) > + { > + ecore_ipc_client_del(e->client); > + return ECORE_CALLBACK_PASS_ON; > + } > extn->ipc.client = e->client; > > - ecore_ipc_client_send(extn->ipc.client, MAJOR, OP_LOCK_FILE, 0, 0, 0, > extn->file.lock, strlen(extn->file.lock + 1)); > + ecore_ipc_client_send(extn->ipc.client, MAJOR, OP_LOCK_FILE, 0, 0, 0, > + extn->file.lock, strlen(extn->file.lock) + 1); > { > Ipc_Data_Resize ipc; > > @@ -1062,8 +1130,8 @@ > ecore_ipc_client_send(extn->ipc.client, MAJOR, OP_SHOW, 0, 0, 0, NULL, > 0); > if (ee->prop.focused) > ecore_ipc_client_send(extn->ipc.client, MAJOR, OP_FOCUS, 0, 0, 0, NULL, > 0); > + _ecore_evas_extn_event(ee, ECORE_EVAS_EXTN_CLIENT_ADD); > return ECORE_CALLBACK_PASS_ON; > - // FIXME: find a way to let app know client came along > } > > static Eina_Bool > @@ -1073,12 +1141,10 @@ > Ecore_Evas *ee = data; > Extn *extn; > > - printf("client del\n"); > extn = ee->engine.buffer.data; > if (!extn) return ECORE_CALLBACK_PASS_ON; > if (extn->ipc.client == e->client) > { > - printf(" my client gone\n"); > evas_object_image_data_set(ee->engine.buffer.image, NULL); > ee->engine.buffer.pixels = NULL; > if (extn->file.shmfile) > @@ -1093,7 +1159,7 @@ > } > extn->ipc.client = NULL; > } > - // FIXME: find a way to let app know client left > + _ecore_evas_extn_event(ee, ECORE_EVAS_EXTN_CLIENT_DEL); > return ECORE_CALLBACK_PASS_ON; > } > > @@ -1305,6 +1371,10 @@ > evas_object_event_callback_add(ee->engine.buffer.image, > EVAS_CALLBACK_HIDE, > _ecore_evas_extn_cb_hide, ee); > + > + evas_object_event_callback_add(ee->engine.buffer.image, > + EVAS_CALLBACK_DEL, > + _ecore_evas_extn_socket_image_obj_del, ee); > > extn = calloc(1, sizeof(Extn)); > if (!extn) > @@ -1372,49 +1442,44 @@ > ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA, > _ipc_client_data, ee)); > } > - // FIXME: need callbacks for pre and post render on a canvas > - // eg like EVAS_CALLBACK_RENDER_FLUSH_PRE/POST but covering all of it > + > extn_ee_list = eina_list_append(extn_ee_list, ee); > ee_target->sub_ecore_evas = eina_list_append(ee_target->sub_ecore_evas, > ee); > - > + > + evas_event_callback_add(ee_target->evas, EVAS_CALLBACK_RENDER_PRE, > + _ecore_evas_extn_socket_targer_render_pre, ee); > + evas_event_callback_add(ee_target->evas, EVAS_CALLBACK_RENDER_POST, > + _ecore_evas_extn_socket_targer_render_post, ee); > return o; > #else > return NULL; > #endif > } > > +EAPI void > +ecore_evas_extn_socket_object_data_lock(Evas_Object *obj) > +{ > +#ifdef EXTN_ENABLED > + Ecore_Evas *ee; > + > + ee = ecore_evas_object_ecore_evas_get(obj); > + if (!ee) return; > + _ecore_evas_socket_lock(ee); > +#endif > +} > > +EAPI void > +ecore_evas_extn_socket_object_data_unlock(Evas_Object *obj) > +{ > +#ifdef EXTN_ENABLED > + Ecore_Evas *ee; > + > + ee = ecore_evas_object_ecore_evas_get(obj); > + if (!ee) return; > + _ecore_evas_socket_unlock(ee); > +#endif > +} > > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > - > #ifdef EXTN_ENABLED > static void > _ecore_evas_plug_resize(Ecore_Evas *ee, int w, int h) > @@ -1506,7 +1571,9 @@ > } > if (ee->engine.buffer.pixels) > { > + _ecore_evas_socket_lock(ee); > updates = evas_render_updates(ee->evas); > + _ecore_evas_socket_unlock(ee); > } > EINA_LIST_FOREACH(updates, l, r) > { > > Modified: trunk/ecore/src/lib/ecore_evas/ecore_evas_private.h > =================================================================== > --- trunk/ecore/src/lib/ecore_evas/ecore_evas_private.h 2011-12-19 05:57:31 > UTC (rev 66319) > +++ trunk/ecore/src/lib/ecore_evas/ecore_evas_private.h 2011-12-19 06:54:08 > UTC (rev 66320) > @@ -418,4 +418,7 @@ > > extern Eina_Bool _ecore_evas_app_comp_sync; > > +void _ecore_evas_extn_init(void); > +void _ecore_evas_extn_shutdown(void); > + > #endif > > > ------------------------------------------------------------------------------ > Learn Windows Azure Live! Tuesday, Dec 13, 2011 > Microsoft is holding a special Learn Windows Azure training event for > developers. It will provide a great way to learn Windows Azure and what it > provides. You can attend the event by watching it streamed LIVE online. > Learn more at http://p.sf.net/sfu/ms-windowsazure > _______________________________________________ > enlightenment-svn mailing list > enlightenment-...@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/enlightenment-svn ------------------------------------------------------------------------------ Learn Windows Azure Live! Tuesday, Dec 13, 2011 Microsoft is holding a special Learn Windows Azure training event for developers. It will provide a great way to learn Windows Azure and what it provides. You can attend the event by watching it streamed LIVE online. Learn more at http://p.sf.net/sfu/ms-windowsazure _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel