GuiLua is basically a redo of my ancient Java based matrix-RAD system, but using Lua and EFL. The ultimate goal is for the various ClientHamr parts to be able to either host their own UI, or have it hosted in the in world 3D window. Matrix-RAD's ability to run either server or client side, with no change to the code, is great for this sort of thing. If I can manage the ability to "tear off" windows, in other words, pull them out of the 3D window to be real windows, then that's something people have been asking for from LL forever. Stdin/out might be good to use. Extantz starts up "client" programs, with a "use stdin/out" argument, the clients pass skang commands (open this internal window with these widgets) to extantz through their stdout, extantz passes skang commands (these values where set by these widgets) back through their stdin. With no "use stdin/out" argument, the programs host their own UI. Perhaps extantz can just pass the UI skang stuff back to the client, which will mean "draw your own window", to support the "tear off" feature. If I remember skang had suitable serialization stuff to support this. Lua does anyway. B-) Naturally, like matrix-RAD, all this UI stuff can happen across a socket as well as through stdin/out. Should be transparent to the user proggy. I can redesign skang to be more Lua like, to take advantage of Lua's meta language capabilities. Since no one used skang anyway, I can get away with this. Also should add a Lua friendly wrapper around nails, so that addons for Extantz can be supplied entirely as Lua scripts. In other words, LuaSL scripts. On top of all that, should also allow access to the Edje Lua stuff I've already written, but drag it outside of an edje file. This pretty much means that GuiLua should be a shared library, coz in the ClientHamr use case, several programs are gonna be using it at once. Should also be separate modules for development stuff like the skin editor, which could be just another proggy using GuiLua. Initially GuiLua can wrap elementary / evas, with the goal of wrapping NAWS, just like matrix-RAD was originally planned. Then I can put off writing NAWS for another decade. lol Design notes ------------ Edje Lua does not wrap elementary widgets, and is not likely to due to elementary being compiled after edje. Smart objects and swallows probably can deal with that though, I'm not familiar enough with them to know. Eo on the other hand allegedly offers introspection, which was always the corner stone of matrix-RAD. So access to elementary widgets via Eo might be possible. That's kinda the entire hook I'm hoping will help to make matrix-RAD style stuff work as well as it did there. Edje Lua is restricted to scripts in edje files, AND sandboxed to those edje files as well. We want to step outside that sandbox, and run stand alone Lua scripts, as well as GuiLua / LuaSL scripts internal to extantz. Some merging of LUaSL and Edje Lua, leaving room for GuiLua, would be great, but I might have to convince Raster. Note that the socket idea wont work in sandboxed edje Lua scripts, unless the socket is in C code, that uses edje messages as the internal transport. Just so it's easier to find, I'll repeat a bit from the Enlightenment mailing list here, the result of discussions with raster and other interested parties - "First step is to write edje functions for generically bundling up one or more Lua tables into a message, sending that message, then unpacking it again. This will be able to be done from edje, from C, and from Lua directly. Perhaps adding that as one more edje messege type. This is for sending Lua tables between threads. A later addition will be to send them through the 'net, probably as eet. Host apps can register arbitrary functions with edje Lua, using a more generic version of the code I already wrote for letting edje register lua functions. These host functions are by default not thread safe. Edje puts a wrapper function around the host app, and registers that wrapper function with Lua. The wrapper function, when called from Lua, does this - ecore_thread_main_loop_begin(); call the host app callback(); ecore_thread_main_loop_end(); The first alternative, which the host app must request, is for the wrapper function to use the table message functions to marshal the arguments, send it to the main thread, wait for the response (or do something else), then unmarshal the result before sending it back to Lua. The second alternative, which the host app must REALLY request, is for the host app to say "I'm REALLY going out of my way to be threadsafe, just call me direct". No edje wrapper function, BUT the host app still has to use edje to register this function. The first two might be done this way - host_cb = edje_lua2_functions_add(...); edje_lua2_function_marshal_set(host_cb, function); The last one could be - host_cb = edje_lua2_threadsafe_function_add(...); Note the difference between _functions_ and _function_. The first call registers an entire metatable full of functions, in the same way that edje does for it's functions. These are the default sort of functions. The second call references one of those previously registered functions, and makes it marshal arguments and results. The third one registers a single function, but it could be added to an existing metatable registered by the first function." and - "We are actually half way there. Anticipating that there would be way more edje and evas stuff to add to the edje Lua API in the future, I created generic wrapper functions to make that easier. Implementing this would mean exposing those static functions, and writing more of these generic wrapper stuff. Lua already provides a mechanism for this sort of thing, but we currently sandbox that out. We can provide a very limited version of the package module, that only lets the Lua script load modules that the host app explicitly provides. This keeps edje Lua in it's strictly sandboxed state." Raster also wants to thread lots of edje, likely including having edje Lua scripts as threads, much like I'm doing with LuaSL already. Plus LuaJIT SPEEEEED!!. B-) EO notes -------- tl;dr - eo introspection doesn't actually exist, even though it was "promised" years ago, but looks trivial to add. object = eo_add(EVAS_OBJ_LINE_CLASS, canvas); evas_line.eo.h -> #define EVAS_OBJ_LINE_CLASS evas_obj_line_class_get() -> const Eo_Class *evas_obj_line_class_get(void) EINA_CONST; evas_line.eo.c -> EO_DEFINE_CLASS(evas_obj_line_class_get, &_evas_line_class_desc, EVAS_OBJ_CLASS, NULL); Eo.h -> EO_DEFINE_CLASS is a macro that basically wraps eo_class_new(), and returns it's result. So Eo_Class is the type of a class, but it's A) opaque, B) deprecated! It includes a pointor to the Eo_Class_Description, which includes the actual name. I'm not seeing anywhere the names of the get/set paramaters being passed into the system, or any way to look up a class based on name. Not even a way to get to the public Eo_Class_Description from the opaque Eo_Class. Eo_Class_Description is at least public. It includes Eo_Op_Description's and Eo_Evenet_Description's. Eo_Op_ and Eo_Event_ include the name and documentation of the op / event. The macro used to generate Eo_Op_ does NOT pass the name, just the ID number as a string. There is also Eo_Op_Func_Description, which does not include a name, it seems to be generated in the constructor. The same Eo_Op_ ID number is used to index it. Seems to be no direct link between Eo_Class and Eo_Op_func_, just the same Eo_Op_ ID numbers used internally somehow. eo_do(obj, evas_obj_line_xy_set(200, 200, 300, 300)); evas_line.eo.h -> #define evas_obj_line_xy_set(x1, y1, x2, y2) EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_SET), EO_TYPECHECK(Evas_Coord , x1), EO_TYPECHECK(Evas_Coord , y1), EO_TYPECHECK(Evas_Coord , x2), EO_TYPECHECK(Evas_Coord , y2) #define EVAS_OBJ_LINE_ID(sub_id) (EVAS_OBJ_LINE_BASE_ID + sub_id) extern EAPI Eo_Op EVAS_OBJ_LINE_BASE_ID; enum { EVAS_OBJ_LINE_SUB_ID_XY_SET, EVAS_OBJ_LINE_SUB_ID_XY_GET, EVAS_OBJ_LINE_SUB_ID_LAST }; evas_line.eo.c -> EAPI Eo_Op EVAS_OBJ_LINE_BASE_ID = EO_NOOP; static void _gen_evas_line_class_constructor(Eo_Class *klass) { const Eo_Op_Func_Description func_desc[] = { EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _eo_obj_evas_line_constructor), EO_OP_FUNC(EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_SET), _eo_obj_evas_line_xy_set), EO_OP_FUNC(EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_GET), _eo_obj_evas_line_xy_get), EO_OP_FUNC_SENTINEL }; eo_class_funcs_set(klass, func_desc); } static void _eo_obj_evas_line_xy_set(Eo *obj, void *_pd, va_list *list) { Evas_Coord x1 = va_arg(*list, Evas_Coord); Evas_Coord y1 = va_arg(*list, Evas_Coord); Evas_Coord x2 = va_arg(*list, Evas_Coord); Evas_Coord y2 = va_arg(*list, Evas_Coord); _evas_line_xy_set(obj, _pd, x1, y1, x2, y2); } void _evas_line_xy_set(Eo *obj, Evas_Line_Data *pd, Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2); evas_object_line.c -> EOLIAN static void _evas_line_xy_set(Eo *eo_obj, Evas_Line_Data *_pd, Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2) Evas_Object_Line *o = eo_data_scope_get(obj, EVAS_OBJ_LINE_CLASS); Evas_Object_Line *o = eo_data_ref(obj, EVAS_OBJ_LINE_CLASS); .. evas_line.eo class Evas_Line (Evas_Object) { legacy_prefix: evas_object_line; eo_prefix: evas_obj_line; properties { xy { set { /*@ @since 1.8 Sets the coordinates of the end points of the given evas line object. */ } get { /*@ Retrieves the coordinates of the end points of the given evas line object. second end point. */ } values { Evas_Coord x1; /*@ The X coordinate of the first point. */ Evas_Coord y1; /*@ The Y coordinate of the first point. */ Evas_Coord x2; /*@ The X coordinate of the second point. */ Evas_Coord y2; /*@ The Y coordinate of the second point. */ } } } implements { Eo_Base::constructor; } } ... evas_line.eo.c EAPI void evas_object_line_xy_set(Evas_Object *obj, Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2) { eo_do((Eo *) obj, evas_obj_line_xy_set(x1, y1, x2, y2)); return ; } static const Eo_Class_Description _evas_line_class_desc = { EO_VERSION, "Evas_Line", EO_CLASS_TYPE_REGULAR, EO_CLASS_DESCRIPTION_OPS(&EVAS_OBJ_LINE_BASE_ID, _evas_line_op_desc, EVAS_OBJ_LINE_SUB_ID_LAST), _evas_line_event_desc, sizeof(Evas_Line_Data), _gen_evas_line_class_constructor, NULL }; skang vs edje vs LL shit ------------------------ EDJE Verbose, complex. Used to place and decorate widget parts. Can be used to place entire widgets through externals and swallows. Basic parts relative to each other. Signals and messages. Embryo scripts. Lua scripts (sandboxed). SKANG Tight, simple. Used to place widgets, and describe actions. Can include some really basic scripting. Widgets in a fixed position, but included stuff for relative placement in the TODO. Automated associations between widget name and variable (and method?) via introspection. Actions. Looks (could easily be extended to edje groups). Extensible. Can be used to pass values around. LL SHIT Verbose, even worse, XML, more crap than is needed. Menus. Windows with widgets relative to each other. Basically nested rectangles. Manual association of widgets to methods. Can include tool tip string, enabled, visible, hover cursor, bounding rectangle?, mouse opaque?, tab groups, font (name, size, style, and alignment). More stuff, typically hidden in the OO somewhere. sigh Generally uses fixed image and colour names, which skins overide. Skins can also overide the XML files. Translations provide override XML files that need only override the text bits. old notes --------- See if it's possible to disable the Emerald/Phoenix/Firestorm LSL bridge when connecting to OpenSim. Actually, they finally came to their senses and support OpenSim now, so that should be sorted already.