Merge branch 'master' into devs/hermet/lottie

This commit is contained in:
Hermet Park 2019-09-11 12:03:18 +09:00
commit 76c48b1600
87 changed files with 714 additions and 489 deletions

View File

@ -207,6 +207,6 @@ collections {
#include "edc/efl/tab_pager.edc"
#include "edc/efl/tab_bar.edc"
#include "edc/efl/tab_page.edc"
#include "edc/efl/item_container.edc"
#include "edc/efl/collection.edc"
#include "edc/efl/group_item.edc"
}

View File

@ -1,3 +1,3 @@
group { "efl/item_container";
group { "efl/collection";
inherit: "efl/scroller";
}

View File

@ -123,7 +123,7 @@ _append_defval(Eina_Strbuf *buf, const Eolian_Expression *exp, const Eolian_Type
}
/* default value or fallback */
const Eolian_Type *btp = eolian_type_aliased_base_get(tp);
if (eolian_type_is_ptr(btp))
if (eolian_type_is_ptr(btp) || strchr(ctp, '*'))
{
eina_strbuf_append(buf, "NULL");
return;
@ -139,11 +139,6 @@ _append_defval(Eina_Strbuf *buf, const Eolian_Expression *exp, const Eolian_Type
free(sn);
return;
}
if (strchr(ctp, '*'))
{
eina_strbuf_append(buf, "NULL");
return;
}
/* enums and remaining regulars... 0 should do */
eina_strbuf_append(buf, "0");
}

View File

@ -52,6 +52,9 @@ struct async_function_declaration_generator
return true;
if (!f.return_type.original_type.visit(is_future{}))
return true;
// C# interfaces can't have non-public members
if(f.scope != attributes::member_scope::scope_public)
return true;
if (!as_generator(
scope_tab << "/// <summary>Async wrapper for <see cref=\"" << name_helpers::managed_method_name(f) << "\" />.</summary>\n"

View File

@ -64,6 +64,18 @@ inline bool is_function_blacklisted(attributes::function_def const& func, Contex
return is_function_blacklisted(c_name);
}
inline bool is_non_public_interface_member(attributes::function_def const& func, attributes::klass_def const&current_klass)
{
if (current_klass.type == attributes::class_type::interface_
|| current_klass.type == attributes::class_type::mixin)
{
if (func.scope != attributes::member_scope::scope_public)
return true;
}
return false;
}
// Blacklist structs that require some kind of manual binding.
inline bool is_struct_blacklisted(std::string const& full_name)

View File

@ -73,6 +73,25 @@ struct documentation_generator
// Klass is needed to check the property naming rulles
attributes::klass_def klass_d((const ::Eolian_Class *)klass, eolian_object_unit_get(klass));
// Comment the block below to enable @see reference conversion for non-public interface members.
// As they are not generated, this causes a doc warning that fails the build, but can be useful to track
// public methods referencing protected stuff.
if (ftype != EOLIAN_PROPERTY)
{
bool is_func_public = ::eolian_function_scope_get(function, ftype) == EOLIAN_SCOPE_PUBLIC;
if (helpers::is_managed_interface(klass_d) && !is_func_public)
return "";
}
else
{
bool is_get_public = ::eolian_function_scope_get(function, EOLIAN_PROP_GET) == EOLIAN_SCOPE_PUBLIC;
bool is_set_public = ::eolian_function_scope_get(function, EOLIAN_PROP_SET) == EOLIAN_SCOPE_PUBLIC;
if (helpers::is_managed_interface(klass_d) && !(is_get_public || is_set_public))
return "";
}
switch(ftype)
{
case ::EOLIAN_METHOD:
@ -112,6 +131,8 @@ struct documentation_generator
static std::string function_conversion(attributes::function_def const& func)
{
// This function is called only from the constructor reference conversion, so it does not
// need to check whether this function non-public in a interface returning an empty reference (yet).
std::string name = name_helpers::klass_full_concrete_or_interface_name(func.klass);
switch (func.type)
{

View File

@ -23,6 +23,10 @@ struct function_declaration_generator
if(blacklist::is_function_blacklisted(f, context) || f.is_static)
return true;
// C# interfaces can't have non-public members
if(f.scope != attributes::member_scope::scope_public)
return true;
if(!as_generator(documentation).generate(sink, f, context))
return false;

View File

@ -81,6 +81,15 @@ struct native_function_definition_generator
.generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
return false;
// We do not generate the wrapper to be called from C for non public interface member directly.
if (blacklist::is_non_public_interface_member(f, *klass))
return true;
// Do not generate static method in interface
if (((klass->type == attributes::class_type::interface_) ||
(klass->type == attributes::class_type::mixin)) && f.is_static)
return true;
// Actual method implementation to be called from C.
std::string return_type;
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
@ -167,9 +176,15 @@ struct function_definition_generator
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
{
EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl;
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
if(blacklist::is_function_blacklisted(f, context))
return true;
// Do not generate static function for concrete class
if (is_concrete && f.is_static)
return true;
std::string return_type;
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
return false;
@ -188,7 +203,7 @@ struct function_definition_generator
self = "";
if(!as_generator
(scope_tab << ((do_super && !f.is_static) ? "virtual " : "") << eolian_mono::function_scope_get(f) << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
(scope_tab << eolian_mono::function_scope_get(f) << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
<< ") {\n "
<< eolian_mono::function_definition_preamble()
<< klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate("
@ -303,12 +318,13 @@ struct property_wrapper_definition_generator
if (blacklist::is_property_blacklisted(property, *implementing_klass, context))
return true;
bool interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
bool is_static = (property.getter.is_engaged() && property.getter->is_static)
|| (property.setter.is_engaged() && property.setter->is_static);
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
if (interface && is_static)
if ((is_concrete || is_interface) && is_static)
return true;
auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0;
@ -389,19 +405,21 @@ struct property_wrapper_definition_generator
std::string scope = "public ";
std::string get_scope = property.getter.is_engaged() ? eolian_mono::function_scope_get(*property.getter) : "";
bool is_get_public = get_scope == "public ";
std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : "";
if (interface)
bool is_set_public = set_scope == "public ";
// No need to generate this wrapper as no accessor is public.
if (is_interface && (!is_get_public && !is_set_public))
return true;
// C# interface members are declared automatically as public
if (is_interface)
{
scope = "";
get_scope = "";
set_scope = "";
}
else if ((property.klass.type == attributes::class_type::mixin) ||
(property.klass.type == attributes::class_type::interface_))
{
get_scope = "";
set_scope = "";
}
else if ((get_scope != "") && (get_scope == set_scope))
{
scope = get_scope;
@ -439,11 +457,12 @@ struct property_wrapper_definition_generator
return false;
}
if (property.getter.is_engaged() && interface)
if (property.getter.is_engaged() && is_interface)
{
if (!as_generator(scope_tab << scope_tab << set_scope << "get;\n"
).generate(sink, attributes::unused, context))
return false;
if (is_get_public)
if (!as_generator(scope_tab << scope_tab << set_scope << "get;\n"
).generate(sink, attributes::unused, context))
return false;
}
else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
{
@ -483,11 +502,12 @@ struct property_wrapper_definition_generator
// return false;
// }
if (property.setter.is_engaged() && interface)
if (property.setter.is_engaged() && is_interface)
{
if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
).generate(sink, attributes::unused, context))
return false;
if (is_set_public)
if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
).generate(sink, attributes::unused, context))
return false;
}
else if (parameters.size() == 1 && property.setter.is_engaged())
{

View File

@ -165,10 +165,6 @@ function_definition_epilogue_generator const as_generator(function_definition_ep
inline std::string function_scope_get(attributes::function_def const& f)
{
if ((f.klass.type == attributes::class_type::mixin) ||
(f.klass.type == attributes::class_type::interface_))
return "public ";
switch (f.scope)
{
case attributes::member_scope::scope_public:
@ -178,7 +174,8 @@ inline std::string function_scope_get(attributes::function_def const& f)
case attributes::member_scope::scope_protected:
return "protected ";
case attributes::member_scope::scope_unknown:
return " ";
// This should trigger a compilation error
return "unkown_scope ";
}
return " ";
}

View File

@ -35,6 +35,11 @@ struct function_registration_generator
if(blacklist::is_function_blacklisted(f, context) || f.is_static) // Static methods aren't overrideable
return true;
// We do not generate registration wrappers for non public interface/mixin members in their concrete classes.
// They go in the first concrete/abstract implementation.
if(blacklist::is_non_public_interface_member(f, *klass))
return true;
if(!as_generator(
indent << "if (" << f.c_name << "_static_delegate == null)\n"
<< indent << "{\n"

View File

@ -233,6 +233,42 @@ std::vector<attributes::function_def> get_all_implementable_methods(attributes::
return ret;
}
template<typename Klass>
inline bool is_managed_interface(Klass const& klass)
{
return klass.type == attributes::class_type::interface_
|| klass.type == attributes::class_type::mixin;
}
/*
* Gets all methods that this class should register (i.e. that comes from it and non-public interface methods
* that this class is the first one implementing)
*/
template<typename Context>
std::vector<attributes::function_def> get_all_registerable_methods(attributes::klass_def const& cls, Context const& context)
{
std::vector<attributes::function_def> ret;
auto implementable_methods = get_all_implementable_methods(cls, context);
std::copy_if(implementable_methods.cbegin(), implementable_methods.cend(), std::back_inserter(ret)
, [&cls](attributes::function_def const & func) {
if (cls == func.klass)
return true;
if (is_managed_interface(func.klass) && func.is_static)
return true;
if (!is_managed_interface(func.klass) || func.scope != attributes::member_scope::scope_public)
return true;
return false;
});
return ret;
}
/*
* Checks whether the given is unique going up the inheritance tree from leaf_klass
*/

View File

@ -31,18 +31,6 @@
namespace eolian_mono {
/* Get the actual number of functions of a class, checking for blacklisted ones */
template<typename Context>
static std::size_t
get_implementable_function_count(grammar::attributes::klass_def const& cls, Context context)
{
auto methods = helpers::get_all_implementable_methods(cls, context);
return std::count_if(methods.cbegin(), methods.cend(), [&context](grammar::attributes::function_def const& func)
{
return !blacklist::is_function_blacklisted(func, context) && !func.is_static;
});
}
template<typename Context>
static bool
is_inherit_context(Context const& context)
@ -198,7 +186,7 @@ struct klass
if(!as_generator
(
documentation
<< "sealed public " << (is_partial ? "partial ":"") << " class " << concrete_name << " :\n"
<< "public sealed " << (is_partial ? "partial ":"") << "class " << concrete_name << " :\n"
<< scope_tab << (root ? "Efl.Eo.EoWrapper" : "") << (klass_full_concrete_or_interface_name % "") << "\n"
<< scope_tab << ", " << interface_name << "\n"
<< scope_tab << *(", " << name_helpers::klass_full_concrete_or_interface_name) << "\n"
@ -239,6 +227,9 @@ struct klass
if (!generate_events(sink, cls, concrete_cxt))
return false;
if (!as_generator(lit("#pragma warning disable CS0628\n")).generate(sink, attributes::unused, concrete_cxt))
return false;
// Parts
if(!as_generator(*(part_definition))
.generate(sink, cls.parts, concrete_cxt)) return false;
@ -263,6 +254,9 @@ struct klass
return false;
}
if (!as_generator(lit("#pragma warning restore CS0628\n")).generate(sink, attributes::unused, concrete_cxt))
return false;
// Copied from nativeinherit class, used when setting up providers.
if(!as_generator(
scope_tab << "private static IntPtr GetEflClassStatic()\n"
@ -398,7 +392,7 @@ struct klass
context);
auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
auto inherit_name = name_helpers::klass_inherit_name(cls);
auto implementable_methods = cls.functions;
auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
bool root = !helpers::has_regular_ancestor(cls);
auto const& indent = current_indentation(inative_cxt);

View File

@ -3,6 +3,7 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.ComponentModel;
@ -47,8 +48,15 @@ public class BindableProperty<T>
throw new InvalidOperationException($"Failed to cast binder {binder} to IPart");
}
var partBinder = partHolder.GetPart(this.partName) as Efl.Ui.IPropertyBind;
// We rely on reflection as GetPart is protected and not generated in IPart.
var partMethod = partHolder.GetType().GetMethod("GetPart", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (partMethod == null)
{
throw new InvalidOperationException($"Failed to get 'GetPart' method on property binder");
}
var partBinder = partMethod.Invoke(partHolder, new System.Object[] { this.partName }) as Efl.Ui.IPropertyBind;
if (partBinder != null)
{
return partBinder.PropertyBind(this.propertyName, modelProperty);

View File

@ -32,9 +32,18 @@ static internal class StrbufNativeMethods
[return: MarshalAsAttribute(UnmanagedType.U1)]
internal static extern bool eina_strbuf_append_char(IntPtr buf, char c);
[DllImport(efl.Libs.Eina)]
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
[return:
MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]
internal static extern string eina_strbuf_string_steal(IntPtr buf);
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
[return:
MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]
internal static extern string eina_strbuf_string_get(IntPtr buf);
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_strbuf_length_get(IntPtr buf); // Uses IntPtr as wrapper for size_t
}
@ -176,8 +185,18 @@ public class Strbuf : IDisposable
throw new ObjectDisposedException(base.GetType().Name);
}
return eina_strbuf_string_steal(Handle);
return eina_strbuf_string_steal(this.Handle);
}
/// <summary>Copy the content of a buffer.</summary>
public override string ToString()
{
if (Disposed)
{
throw new ObjectDisposedException(base.GetType().Name);
}
return eina_strbuf_string_get(this.Handle);
}
}
} // namespace eina

View File

@ -173,7 +173,10 @@ static internal class UnsafeNativeMethods
internal static extern int eina_value_compare_wrapper(IntPtr handle, IntPtr other);
[DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
internal static extern IntPtr eina_value_to_string(IntPtr handle); // We take ownership of the returned string.
[return:
MarshalAs(UnmanagedType.CustomMarshaler,
MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]
internal static extern string eina_value_to_string(IntPtr handle); // We take ownership of the returned string.
[DllImport(efl.Libs.CustomExports)]
[return: MarshalAsAttribute(UnmanagedType.U1)]
@ -2611,10 +2614,8 @@ public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
public override String ToString()
{
SanityChecks();
IntPtr ptr = eina_value_to_string(this.Handle);
String str = Marshal.PtrToStringAnsi(ptr);
MemoryNative.Free(ptr);
return str;
return eina_value_to_string(this.Handle);
}
/// <summary>Empties an optional Eina.Value, freeing what was previously contained.</summary>

View File

@ -44,30 +44,6 @@ public struct Efl_Object_Ops
public UIntPtr count;
};
#pragma warning disable 0169
public struct EvasObjectBoxLayout
{
IntPtr o;
IntPtr priv;
IntPtr user_data;
};
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct EvasObjectBoxData
{
}
public struct EvasObjectBoxOption
{
IntPtr obj;
[MarshalAsAttribute(UnmanagedType.U1)] bool max_reached;
[MarshalAsAttribute(UnmanagedType.U1)] bool min_reached;
Evas.Coord alloc_size;
};
#pragma warning restore 0169
namespace Efl
{
@ -212,8 +188,6 @@ public struct TextAnnotateAnnotation
[MarshalAsAttribute(UnmanagedType.U1)]bool is_item;
}
public delegate void SignalCb(IntPtr data, IntPtr obj, IntPtr emission, IntPtr source);
namespace Access
{
@ -229,85 +203,7 @@ public struct ActionData
} // namespace Efl
namespace Evas
{
public struct Coord
{
int val;
public Coord(int value)
{
val = value;
}
static public implicit operator Coord(int val)
{
return new Coord(val);
}
static public implicit operator int(Coord coord)
{
return coord.val;
}
}
/* Copied from Evas_Legacy.h */
public enum TextStyleType
{
///<summary> plain, standard text.</summary>
Plain = 0,
///<summary> text with shadow underneath.</summary>
Shadow,
///<summary> text with an outline.</summary>
Outline,
///<summary> text with a soft outline.</summary>
SoftOutline,
///<summary> text with a glow effect.</summary>
Glow,
///<summary> text with both outline and shadow effects.</summary>
OutlineShadow,
///<summary> text with (far) shadow underneath.</summary>
FarShadow,
///<summary> text with outline and soft shadow effects combined.</summary>
OutlineSoftShadow,
///<summary> text with (soft) shadow underneath.</summary>
SoftShadow,
///<summary> text with (far soft) shadow underneath.</summary>
FarSoftShadow,
// Shadow direction modifiers
///<summary> shadow growing to bottom right.</summary>
ShadowDirectionBottomRight = 0 /* 0 >> 4 */,
///<summary> shadow growing to the bottom.</summary>
ShadowDirectionBottom = 16 /* 1 >> 4 */,
///<summary> shadow growing to bottom left.</summary>
ShadowDirectionBottomLeft = 32 /* 2 >> 4 */,
///<summary> shadow growing to the left.</summary>
ShadowDirectionLeft = 48 /* 3 >> 4 */,
///<summary> shadow growing to top left.</summary>
ShadowDirectionTopLeft = 64 /* 4 >> 4 */,
///<summary> shadow growing to the top.</summary>
ShadowDirectionTop = 80 /* 5 >> 4 */,
///<summary> shadow growing to top right.</summary>
ShadowDirectionTopRight = 96 /* 6 >> 4 */,
///<summary> shadow growing to the right.</summary>
ShadowDirectionRight = 112 /* 7 >> 4 */
};
} // namespace Evas
// Global delegates
public delegate int Eina_Compare_Cb(IntPtr a, IntPtr b);
public delegate void ElmInterfaceScrollableCb(IntPtr obj, IntPtr data);
public delegate void ElmInterfaceScrollableMinLimitCb(IntPtr obj,
[MarshalAsAttribute(UnmanagedType.U1)]bool w,
[MarshalAsAttribute(UnmanagedType.U1)]bool h);
public delegate void ElmInterfaceScrollableResizeCb(IntPtr obj, Evas.Coord w, Evas.Coord h);
[return: MarshalAsAttribute(UnmanagedType.U1)]
public delegate bool ElmMultibuttonentryItemFilterCb(IntPtr obj, IntPtr item_label, IntPtr item_data, IntPtr data);
public delegate IntPtr ElmMultibuttonentryFormatCb(int count, IntPtr data);
public delegate void EinaFreeCb(IntPtr data);
public delegate void EvasSmartCb(IntPtr data, IntPtr obj, IntPtr event_info);
public delegate void ElmObjectItemSignalCb(IntPtr data, IntPtr item, IntPtr emission, IntPtr source);
public delegate void ElmTooltipItemContentCb(IntPtr data, IntPtr obj, IntPtr tooltip, IntPtr item);

View File

@ -5,8 +5,8 @@
#include <Eo.h>
#include <Efl_Core.h>
static void _read_change(void *data EINA_UNUSED, const Efl_Event *ev);
static Eina_Value _task_exit(void *data, Eina_Value v, const Eina_Future *dead EINA_UNUSED);
static void _read_change(void *data EINA_UNUSED, const Efl_Event *ev);
static void _task_exit(void *data EINA_UNUSED, const Efl_Event *ev);
static void
_read_change(void *data EINA_UNUSED, const Efl_Event *ev)
@ -27,16 +27,19 @@ _read_change(void *data EINA_UNUSED, const Efl_Event *ev)
}
}
static Eina_Value
_task_exit(void *data, Eina_Value v, const Eina_Future *dead EINA_UNUSED)
static void
_task_exit(void *data EINA_UNUSED, const Efl_Event *ev)
{
// called when the task says it has completed and exited.
// all output to read has stopped
Eo *obj = data;
Eo *obj = ev->object;
printf("--- [%p] EXITED exit_code=%i\n", obj, efl_task_exit_code_get(obj));
efl_loop_quit(efl_provider_find(obj, EFL_LOOP_CLASS), eina_value_int_init(99));
efl_del(obj);
return v;
// exe auto deleted at this point like efl threads. more convenient as
// you don't need to remember to delete them yourself if launching
// lots of commands - this is how ecore_exe worked. so listen to the
// exit event (or del event) if you care about this... or ref it to keep
// it around longer.
}
EAPI_MAIN void
@ -55,7 +58,8 @@ efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
efl_exe_env_set(efl_added, env),
efl_task_flags_set(efl_added, EFL_TASK_FLAGS_USE_STDOUT | EFL_TASK_FLAGS_USE_STDIN),
efl_event_callback_add(efl_added, EFL_IO_READER_EVENT_CAN_READ_CHANGED, _read_change, NULL),
eina_future_then(efl_task_run(efl_added), _task_exit, efl_added)
efl_event_callback_add(efl_added, EFL_TASK_EVENT_EXIT, _task_exit, NULL),
efl_task_run(efl_added)
);
efl_unref(env);

View File

@ -8,7 +8,7 @@
static void _th_read_change(void *data EINA_UNUSED, const Efl_Event *ev);
static void _th_main(void *data EINA_UNUSED, const Efl_Event *ev);
static void _read_change(void *data EINA_UNUSED, const Efl_Event *ev);
static Eina_Value _task_exit(void *data, Eina_Value v, const Eina_Future *dead EINA_UNUSED);
static void _task_exit(void *data EINA_UNUSED, const Efl_Event *ev);
////////////////////////////////////////////////////////////////////////////
//// thread side of code
@ -85,7 +85,8 @@ _th_main(void *data EINA_UNUSED, const Efl_Event *ev)
efl_task_flags_set(efl_added, EFL_TASK_FLAGS_USE_STDOUT | EFL_TASK_FLAGS_USE_STDIN | EFL_TASK_FLAGS_EXIT_WITH_PARENT),
efl_event_callback_add(efl_added, EFL_LOOP_EVENT_ARGUMENTS, _th_main, NULL),
efl_event_callback_add(efl_added, EFL_IO_READER_EVENT_CAN_READ_CHANGED, _read_change, NULL),
eina_future_then(efl_task_run(efl_added), _task_exit, efl_added)
efl_event_callback_add(efl_added, EFL_TASK_EVENT_EXIT, _task_exit, NULL),
efl_task_run(efl_added)
);
char *buf2 = "hello-out-there2 ";
@ -117,18 +118,17 @@ _read_change(void *data EINA_UNUSED, const Efl_Event *ev)
}
}
static Eina_Value
_task_exit(void *data, Eina_Value v, const Eina_Future *dead EINA_UNUSED)
static void
_task_exit(void *data EINA_UNUSED, const Efl_Event *ev)
{
// called when the task says it has completed and exited.
// all output to read has stopped
Eo *obj = data;
Eo *obj = ev->object;
printf("--- [%p] EXITED exit_code=%i outdata=%p\n", obj, efl_task_exit_code_get(obj), efl_threadio_outdata_get(obj));
// thread object will be automatically deleted after as long as
// EFL_TASK_FLAGS_EXIT_WITH_PAREN is set on task flags, and this is
// EFL_TASK_FLAGS_EXIT_WITH_PARENT is set on task flags, and this is
// actually the default unless you change the flags to be something
// else. if you don't use this then the task/thread becomes orphaned
return v;
}
////////////////////////////////////////////////////////////////////////////
@ -181,7 +181,8 @@ efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
efl_task_flags_set(efl_added, EFL_TASK_FLAGS_USE_STDOUT | EFL_TASK_FLAGS_USE_STDIN | EFL_TASK_FLAGS_EXIT_WITH_PARENT),
efl_event_callback_add(efl_added, EFL_LOOP_EVENT_ARGUMENTS, _th_main, NULL),
efl_event_callback_add(efl_added, EFL_IO_READER_EVENT_CAN_READ_CHANGED, _read_change, NULL),
eina_future_then(efl_task_run(efl_added), _task_exit, efl_added)
efl_event_callback_add(efl_added, EFL_TASK_EVENT_EXIT, _task_exit, NULL),
efl_task_run(efl_added)
);
char *buf2 = "hello-out-there ";

View File

@ -15,7 +15,7 @@ class @beta Ecore.Event.Message extends Efl.Loop_Message
}
data_steal {
[[ Steal the data out and set internal values to -1
for type and NULL for other vals ]]
for type and $NULL for other vals ]]
params {
@out type: int; [[ The event type ]]
@out data: void_ptr; [[ The event data ]]

View File

@ -26,7 +26,7 @@ abstract Efl.App extends Efl.Loop implements Efl.Core.Command_Line
]]
get {}
values {
version: ptr(const(Efl.Version)); [[Efl build version]]
version: const(Efl.Version) @by_ref; [[Efl build version]]
}
}
@property efl_version {
@ -36,7 +36,7 @@ abstract Efl.App extends Efl.Loop implements Efl.Core.Command_Line
]]
get {}
values {
version: ptr(const(Efl.Version)); [[Efl version]]
version: const(Efl.Version) @by_ref; [[Efl version]]
}
}
}

View File

@ -203,6 +203,16 @@ _remove_invalid_chars(char *command)
}
}
static void
_clear_command(Efl_Core_Command_Line_Data *pd)
{
if (!pd->command) return;
while (eina_array_count(pd->command) > 0)
eina_stringshare_del(eina_array_pop(pd->command));
eina_array_free(pd->command);
pd->command = NULL;
}
EOLIAN static Eina_Bool
_efl_core_command_line_command_array_set(Eo *obj EINA_UNUSED, Efl_Core_Command_Line_Data *pd, Eina_Array *array)
{
@ -210,6 +220,7 @@ _efl_core_command_line_command_array_set(Eo *obj EINA_UNUSED, Efl_Core_Command_L
Eina_Strbuf *command = eina_strbuf_new();
unsigned int i = 0;
_clear_command(pd);
pd->command = eina_array_new(array ? eina_array_count(array) : 0);
for (i = 0; i < (array ? eina_array_count(array) : 0); ++i)
{
@ -219,7 +230,6 @@ _efl_core_command_line_command_array_set(Eo *obj EINA_UNUSED, Efl_Core_Command_L
if (!param)
{
free(param);
while (eina_array_count(pd->command) > 0)
eina_stringshare_del(eina_array_pop(pd->command));
eina_array_free(pd->command);
@ -276,4 +286,12 @@ _efl_core_command_line_command_string_set(Eo *obj EINA_UNUSED, Efl_Core_Command_
return EINA_TRUE;
}
EOLIAN static void
_efl_core_command_line_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Core_Command_Line_Data *pd)
{
free(pd->string_command);
pd->string_command = NULL;
_clear_command(pd);
efl_destructor(efl_super(obj, MY_CLASS));
}
#include "efl_core_command_line.eo.c"

View File

@ -1,4 +1,4 @@
mixin @beta Efl.Core.Command_Line {
mixin @beta Efl.Core.Command_Line requires Efl.Object {
[[A mixin that implements standard functions for command lines.
This object parses the command line that gets passed, later the object can be accessed via accessor or the string
@ -79,4 +79,7 @@ mixin @beta Efl.Core.Command_Line {
}
}
implements {
Efl.Object.destructor;
}
}

View File

@ -56,7 +56,6 @@ struct _Efl_Exe_Data
Eina_Bool can_write : 1;
} fd;
#else
Eina_Promise *promise;
Eo *exit_handler;
pid_t pid;
struct {
@ -178,47 +177,8 @@ _exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
(pd->fd.exited_read == -1) && (!pd->exit_called))
{
pd->exit_called = EINA_TRUE;
if (pd->promise)
{
Eina_Promise *p = pd->promise;
int exit_code = efl_task_exit_code_get(obj);
if ((exit_code != 0) && (!(efl_task_flags_get(obj) &
EFL_TASK_FLAGS_NO_EXIT_CODE_ERROR)))
{
Eina_Error err = exit_code + 1000000;
// Code Meaning Example Comments
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
// 1 Catchall for general errors let "var1 = 1/0" Miscellaneous errors, such as "divide by zero" and other impermissible operations
// 2 Misuse of shell builtins empty_function() {} Missing keyword or command, or permission problem (and diff return code on a failed binary file comparison).
// 126 Command invoked cannot execute /dev/null Permission problem or command is not an executable
// 127 "command not found" illegal_command Possible problem with $PATH or a typo
// 128 Invalid argument to exit exit 3.14159 exit takes only integer args in the range 0 - 255 (see first footnote)
// 128+n Fatal error signal "n" kill -9 $PPID $? returns 137 (128 + 9)
// 130 Script terminated by Control-C Ctl-C Control-C is fatal error signal 2, (130 = 128 + 2, see above)
// 255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255
//
// According to the above table, exit codes 1 - 2,
// 126 - 165, and 255 [1] have special meanings, and
// should therefore be avoided for user-specified exit
// parameters. Ending a script with exit 127 would
// certainly cause confusion when troubleshooting (is
// the error code a "command not found" or a user-defined
// one?). However, many scripts use an exit 1 as a general
// bailout-upon-error. Since exit code 1 signifies so many
// possible errors, it is not particularly useful in
// debugging.
if (exit_code == 1 ) err = EBADF;
else if (exit_code == 2 ) err = EDOM;
else if (exit_code == 126) err = ENOEXEC;
else if (exit_code == 127) err = ENOENT;
else if (exit_code == 128) err = EINVAL;
else if (exit_code == 129) err = EFAULT;
else if (exit_code == 130) err = EINTR;
else if ((exit_code >= 131) && (exit_code <= 165)) err = EFAULT;
eina_promise_reject(p, err);
}
else eina_promise_resolve(p, eina_value_int_init(exit_code));
}
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
efl_del(obj);
}
}
@ -268,24 +228,6 @@ _cb_exe_in(void *data, const Efl_Event *event EINA_UNUSED)
Eo *obj = data;
efl_io_writer_can_write_set(obj, EINA_TRUE);
}
static Eina_Value
_run_cancel_cb(Efl_Loop_Consumer *consumer, void *data EINA_UNUSED, Eina_Error error)
{
if (error == ECANCELED) efl_task_end(consumer);
return eina_value_error_init(error);
}
static void
_run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,
void *data,
const Eina_Future *dead_future EINA_UNUSED)
{
Efl_Exe_Data *pd = data;
pd->promise = NULL;
}
#endif
//////////////////////////////////////////////////////////////////////////
@ -399,7 +341,7 @@ _efl_exe_efl_task_priority_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
return pri;
}
EOLIAN static Eina_Future *
EOLIAN static Eina_Bool
_efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
#ifdef _WIN32
@ -414,20 +356,20 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
int pipe_exited[2];
int ret;
if (pd->run) return NULL;
if (pd->pid != -1) return NULL;
if (!td) return NULL;
if (pd->run) return EINA_FALSE;
if (pd->pid != -1) return EINA_FALSE;
if (!td) return EINA_FALSE;
// get a cmdline to run
cmd = efl_core_command_line_command_get(obj);
if (!cmd) return NULL;
if (!cmd) return EINA_FALSE;
ret = pipe(pipe_exited);
if (EINA_UNLIKELY(ret != 0))
{
const int error = errno;
ERR("pipe() failed: %s", strerror(error));
return NULL;
return EINA_FALSE;
}
pd->fd.exited_read = pipe_exited[0];
@ -442,7 +384,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
const int error = errno;
ERR("pipe() failed: %s", strerror(error));
return NULL;
return EINA_FALSE;
}
pd->fd.in = pipe_stdin[1];
if (fcntl(pd->fd.in, F_SETFL, O_NONBLOCK) < 0)
@ -461,7 +403,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
const int error = errno;
ERR("pipe() failed: %s", strerror(error));
return NULL;
return EINA_FALSE;
}
pd->fd.out = pipe_stdout[0];
if (fcntl(pd->fd.out, F_SETFL, O_NONBLOCK) < 0)
@ -488,7 +430,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
_close_fds(pd);
_ecore_signal_pid_unlock();
return NULL;
return EINA_FALSE;
}
// register this pid in the core sigchild/pid exit code watcher
_ecore_signal_pid_register(pd->pid, pd->fd.exited_write);
@ -502,11 +444,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
EFL_LOOP_HANDLER_FLAGS_READ));
_ecore_signal_pid_unlock();
pd->run = EINA_TRUE;
pd->promise = efl_loop_promise_new(obj);
return efl_future_then(obj, eina_future_new(pd->promise),
.data = pd,
.error = _run_cancel_cb,
.free = _run_clean_cb);
return EINA_TRUE;
}
// this code is in the child here, and is temporary setup until we
// exec() the child to replace everything.
@ -609,7 +547,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
(errno == ENOEXEC) || (errno == ENOMEM))
exit(126);
exit(127);
return NULL;
return EINA_FALSE;
#endif
}
@ -651,7 +589,7 @@ _efl_exe_efl_object_destructor(Eo *obj, Efl_Exe_Data *pd)
{
#ifdef _WIN32
#else
if (pd->promise)
if (!pd->exit_called)
ERR("Exe being destroyed while child has not exited yet.");
if (pd->fd.exited_read >= 0)
{

View File

@ -15,7 +15,7 @@ enum @beta Efl.Exe_Signal {
}
enum @beta Efl.Exe_Flags {
[[Flags to customize task behavior.]] // TODO: This needs more detail.
[[Flags to customize process behavior.]]
none = 0, [[No special flags.]]
group_leader = 1, [[Process will be executed in its own session.]]
hide_io = 4 [[All console IO will be hidden.]]
@ -23,16 +23,21 @@ enum @beta Efl.Exe_Flags {
class @beta Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Efl.Core.Command_Line
{
[[Further customization of @Efl.Task, including signals and environment control.]] // TODO: This needs more detail
[[This is a specialized @Efl.Task which abstracts an operating system process.
This class provides a way to start a task by running an executable file (specified using the
@Efl.Core.Command_Line interface) and further customize its execution flags (@.exe_flags) and
environment variables (@.env).
It also allows communicating with the process through signals (@.signal).
]]
methods {
signal {
[[Send a signal to this task.]]
[[Send a signal to this process.]]
params {
sig: Efl.Exe_Signal; [[Signal number to send.]]
}
}
@property exe_flags {
[[Customize the task's behavior.]]
[[Customize the process' behavior.]]
set { }
get { }
values {
@ -40,17 +45,17 @@ class @beta Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Ef
}
}
@property exit_signal {
[[The final exit signal of this task.]]
[[The signal this process emitted upon exiting, if any.]]
get { }
values {
sig: int; [[The exit signal, or -1 if no exit signal happened.]]
}
}
@property env {
[[If $env is $null then the process created by this object is
[[If $env is $NULL then the process created by this object is
going to inherit the environment of this process.
In case $env is not $null then the environment variables declared
In case $env is not $NULL then the environment variables declared
in this object will represent the environment passed to the new process.
]]
get {

View File

@ -147,7 +147,7 @@ class @beta Efl.Io.Copier extends Efl.Loop_Consumer implements Efl.Io.Closer {
If @.source is flagged "eos" and all data is written to the
destination then the "done" event is emitted.
If the destination is not set (ie: NULL) then data is kept
If the destination is not set (ie: $NULL) then data is kept
in a internal @Eina.Binbuf, which can be stolen with
@.binbuf_steal once "data" or "line" events are
emitted. It exists as a useful shortcut to easily drain

View File

@ -642,21 +642,11 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
_app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
}
EOLIAN static Eina_Future *
EOLIAN static Eina_Bool
_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
{
Eina_Value *ret;
int real;
ret = efl_loop_begin(obj);
real = efl_loop_exit_code_process(ret);
if (real == 0)
{
// we never return a valid future here because there is no loop
// any more to process the future callback as we would have quit
return NULL;
}
return NULL;
efl_loop_exit_code_process(efl_loop_begin(obj));
return EINA_TRUE;
}
EOLIAN static void

View File

@ -51,8 +51,8 @@ abstract Efl.Loop_Consumer extends Efl.Object
promise_new @const {
[[Create a new promise with the scheduler coming from the loop provided by this object.
Note: You should not use eina_promise_data_set as this function rely on controlling the promise data.]]
return: ptr(Eina.Promise) @move; [[The new promise.]]
Note: You should not use eina_promise_data_set as this function rely on controlling the promise data.]]
return: Eina.Promise @move @by_ref; [[The new promise.]]
}
}
implements {

View File

@ -54,15 +54,16 @@ abstract Efl.Task extends Efl.Loop_Consumer
}
run @pure_virtual {
[[Actually run the task.]]
return: future<void> @move; [[A future triggered when task exits and is passed int exit code.]]
return: bool; [[On success in starting the task, return true, otherwise false]]
}
end @pure_virtual {
[[Request the task end (may send a signal or interrupt
signal resulting in a terminate event being tiggered in the
signal resulting in a terminate event being triggered in the
target task loop).]]
}
}
events {
exit: void; [[Called when the task exits. You can pick up any information you need at this point such as exit_code etc.]]
}
implements {
Efl.Object.constructor;

View File

@ -68,7 +68,6 @@ struct _Efl_Thread_Data
Eina_Bool can_write : 1;
} fd, ctrl;
int read_listeners;
Eina_Promise *promise;
Eo *loop;
Thread_Data *thdat;
Efl_Callback_Array_Item_Full *event_cb;
@ -363,15 +362,7 @@ _thread_exit_eval(Eo *obj, Efl_Thread_Data *pd)
{
pd->exit_called = EINA_TRUE;
if (pd->thdat) efl_threadio_outdata_set(obj, pd->thdat->outdata);
if (pd->promise)
{
Eina_Promise *p = pd->promise;
int exit_code = efl_task_exit_code_get(obj);
if ((exit_code != 0) && (!(efl_task_flags_get(obj) &
EFL_TASK_FLAGS_NO_EXIT_CODE_ERROR)))
eina_promise_reject(p, exit_code + 1000000);
else eina_promise_resolve(p, eina_value_int_init(exit_code));
}
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
efl_del(obj);
}
}
@ -448,22 +439,6 @@ _cb_thread_parent_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
//////////////////////////////////////////////////////////////////////////
static Eina_Value
_run_cancel_cb(Efl_Loop_Consumer *consumer, void *data EINA_UNUSED, Eina_Error error)
{
if (error == ECANCELED) efl_task_end(consumer);
return eina_value_error_init(error);
}
static void
_run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,void *data, const Eina_Future *dead_future EINA_UNUSED)
{
Efl_Thread_Data *pd = data;
pd->promise = NULL;
}
static void
_thread_parent_read_listeners_modify(Efl_Thread_Data *pd, int mod)
{
@ -613,7 +588,7 @@ _efl_thread_efl_object_finalize(Eo *obj, Efl_Thread_Data *pd EINA_UNUSED)
EOLIAN static void
_efl_thread_efl_object_destructor(Eo *obj, Efl_Thread_Data *pd)
{
if (pd->promise)
if (pd->exit_called)
ERR("Thread being destroyed while real worker has not exited yet.");
if (pd->thdat)
{
@ -664,7 +639,7 @@ _task_run_pipe_fail_clear(Thread_Data *thdat, Efl_Thread_Data *pd)
free(thdat);
}
EOLIAN static Eina_Future *
EOLIAN static Eina_Bool
_efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
{
Eina_Thread_Priority pri;
@ -676,10 +651,10 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
Efl_Callback_Array_Item_Full *it;
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
if (pd->run) return NULL;
if (!td) return NULL;
if (pd->run) return EINA_FALSE;
if (!td) return EINA_FALSE;
thdat = calloc(1, sizeof(Thread_Data));
if (!thdat) return NULL;
if (!thdat) return EINA_FALSE;
thdat->fd.in = -1;
thdat->fd.out = -1;
thdat->ctrl.in = -1;
@ -695,7 +670,7 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
{
ERR("Can't create to_thread pipe");
free(thdat);
return NULL;
return EINA_FALSE;
}
}
if (td->flags & EFL_TASK_FLAGS_USE_STDOUT)
@ -709,7 +684,7 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
close(pipe_from_thread[1]);
}
free(thdat);
return NULL;
return EINA_FALSE;
}
}
if (td->flags & EFL_TASK_FLAGS_USE_STDIN)
@ -752,7 +727,7 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
{
ERR("Can't create to_thread control pipe");
_task_run_pipe_fail_clear(thdat, pd);
return NULL;
return EINA_FALSE;
}
if (pipe(pipe_from_thread) != 0)
{
@ -760,7 +735,7 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
_task_run_pipe_fail_clear(thdat, pd);
close(pipe_to_thread[0]);
close(pipe_to_thread[1]);
return NULL;
return EINA_FALSE;
}
thdat->ctrl.in = pipe_from_thread[1]; // write - input to parent
thdat->ctrl.out = pipe_to_thread [0]; // read - output from parent
@ -864,13 +839,11 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
pd->fd.out = -1;
pd->ctrl.in = -1;
pd->ctrl.out = -1;
return NULL;
return EINA_FALSE;
}
pd->thdat = thdat;
pd->run = EINA_TRUE;
pd->promise = efl_loop_promise_new(obj);
return efl_future_then(obj, eina_future_new(pd->promise),
.data = pd, .error = _run_cancel_cb, .free = _run_clean_cb);
return EINA_TRUE;
}
EOLIAN static void

View File

@ -89,7 +89,7 @@ abstract @beta Ecore.Audio extends Efl.Object
data: void_ptr; [[User data to pass to the VIO functions]]
free_func: efl_key_data_free_func; [[This function takes care to
clean up $data when he VIO is
destroyed. NULL means do
destroyed. $NULL means do
nothing.
]]
}

View File

@ -74,7 +74,7 @@ interface @beta Efl.Net.Dialer extends Efl.Net.Socket {
'http'.
Whenever appropriate dialers may use system proxy if the
proxy is NULL (the default). To forcefully disable
proxy is $NULL (the default). To forcefully disable
proxy, use an empty string ("").
- http://username:password\@proxyserver:port
@ -91,7 +91,7 @@ interface @beta Efl.Net.Dialer extends Efl.Net.Socket {
get { }
set { }
values {
proxy_url: string; [[May be empty or NULL to unset]]
proxy_url: string; [[May be empty or $NULL to unset]]
}
}

View File

@ -31,7 +31,7 @@ class @beta Efl.Net.Dialer_Http extends Efl.Loop_Consumer implements Efl.Net.Dia
To enable debugging use EINA_LOG_LEVELS=ecore_con:4 environment
variable.
If the proxy is NULL (default), then the system proxy will be
If the proxy is $NULL (default), then the system proxy will be
used. On UNIX that's the environment variable $http_proxy (or
'$all_proxy') is used if the given address doesn't match
$no_proxy patterns. To disable proxy use an empty string. If
@ -259,7 +259,7 @@ class @beta Efl.Net.Dialer_Http extends Efl.Loop_Consumer implements Efl.Net.Dia
Since multiple requests can occur if @.allow_redirects
is true, then all headers will be accumulated. To know
when a new request's been started, check for headers with keys
being NULL. The value will be the "HTTP/VERSION RESPONSE"
being $NULL. The value will be the "HTTP/VERSION RESPONSE"
string received from the host, such as:
- key=NULL, value="HTTP/1.1 302 Found"
@ -381,7 +381,7 @@ class @beta Efl.Net.Dialer_Http extends Efl.Loop_Consumer implements Efl.Net.Dia
params {
epochtime: int64; [[UNIX Epoch time - seconds since 1/1/1970]]
}
return: mstring @move @no_unused; [[Newly allocated null-terminated string on success or NULL on errors]]
return: mstring @move @no_unused; [[Newly allocated null-terminated string on success or $NULL on errors]]
}
}

View File

@ -4,12 +4,12 @@ class @beta Efl.Net.Dialer_Ssl extends Efl.Net.Socket_Ssl implements Efl.Net.Dia
This creates an internal @Efl.Net.Dialer_Tcp and once connected
it will start the SSL handshake.
If the proxy is NULL (default), then the system proxy will be
If the proxy is $NULL (default), then the system proxy will be
used. On UNIX that's the environment variable $socks_proxy (or
'$proxy' or '$all_proxy') is used if the given address doesn't
match $no_proxy patterns. To disable proxy use an empty string.
If the proxy is NULL (default), then the system proxy will be
If the proxy is $NULL (default), then the system proxy will be
used. On UNIX that's the environment variable $socks_proxy (or
'$all_proxy') is used if the given address doesn't match
$no_proxy patterns. To disable proxy use an empty string. If

View File

@ -1,12 +1,12 @@
class @beta Efl.Net.Dialer_Tcp extends Efl.Net.Socket_Tcp implements Efl.Net.Dialer {
[[Connects to a remote TCP server.
If the proxy is NULL (default), then the system proxy will be
If the proxy is $NULL (default), then the system proxy will be
used. On UNIX that's the environment variable $socks_proxy (or
'$proxy' or '$all_proxy') is used if the given address doesn't
match $no_proxy patterns. To disable proxy use an empty string.
If the proxy is NULL (default), then the system proxy will be
If the proxy is $NULL (default), then the system proxy will be
used. On UNIX that's the environment variable $socks_proxy (or
'$all_proxy') is used if the given address doesn't match
$no_proxy patterns. To disable proxy use an empty string. If

View File

@ -52,7 +52,7 @@ class @beta Efl.Net.Dialer_Websocket extends Efl.Loop_Consumer implements Efl.Ne
not a subclass and thus not all HTTP features are exposed as the
WebSocket has strict requirements that must be respected.
If the proxy is NULL (default), then the system proxy will be
If the proxy is $NULL (default), then the system proxy will be
used. On UNIX that's the environment variable $http_proxy (or
'$all_proxy') is used if the given address doesn't match
$no_proxy patterns. To disable the proxy use an empty string. If

View File

@ -85,7 +85,7 @@ class @beta Efl.Net.Ip_Address extends Efl.Object {
params {
numeric_address: string; [[The numeric address to parse, such as '127.0.0.1:1234' or '[::1]:1234']]
}
return: Efl.Net.Ip_Address @move; [[The new IP address object or NULL if it failed to parse]]
return: Efl.Net.Ip_Address @move; [[The new IP address object or $NULL if it failed to parse]]
}
resolve @static {

View File

@ -34,10 +34,10 @@ class @beta Efl.Net.Session extends Efl.Loop_Consumer {
Some platforms may not implement the backend for this class. In
this cases the system will report always @.state "online"
(@Efl.Net.Session_State.online) and other properties will be
NULL, such as @.network_name, @.interface, @.ipv4 and @.ipv6; as well as
$NULL, such as @.network_name, @.interface, @.ipv4 and @.ipv6; as well as
@.technology is set to @Efl.Net.Session_Technology.unknown. As such
if you need to detect for an actual backend, check if the
state is online but those properties are NULL or technology is
state is online but those properties are $NULL or technology is
unknown.
Note: the @.connect method is subject to backend policy. For
@ -92,7 +92,7 @@ class @beta Efl.Net.Session extends Efl.Loop_Consumer {
Note: if there is no backend for this class, then state
will be always online, however @.technology will be
unknown, @.interface, @.network_name, @.ipv4 and @.ipv6 will be
NULL.
$NULL.
]]
get { }
values {

View File

@ -37,8 +37,8 @@ class @beta Efl.Net.Socket_Ssl extends Efl.Loop_Consumer implements Efl.Net.Sock
return: bool(false); [[$true if adopted, $false otherwise]]
}
values {
efl_net_socket: Efl.Net.Socket; [[The adopted object, if any, otherwise NULL]]
ctx: Efl.Net.Ssl.Context; [[The SSL context used when adopting the socket, if any, otherwise NULL]]
efl_net_socket: Efl.Net.Socket; [[The adopted object, if any, otherwise $NULL]]
ctx: Efl.Net.Ssl.Context; [[The SSL context used when adopting the socket, if any, otherwise $NULL]]
}
}
@ -68,7 +68,7 @@ class @beta Efl.Net.Socket_Ssl extends Efl.Loop_Consumer implements Efl.Net.Sock
address but the server certificate only specifies DNS
(names).
If NULL, then it will fetch from socket using
If $NULL, then it will fetch from socket using
@Efl.Net.Socket.address_remote or
@Efl.Net.Dialer.address_dial.

View File

@ -115,7 +115,7 @@ class @beta Efl.Net.Ssl.Context extends Efl.Object {
This is useful to avoid replicating a hostname in all
socket wrapper with hostname_override.
If NULL, then sockets wrappers will will fetch from
If $NULL, then sockets wrappers will will fetch from
adopted socket using address_remote or
address_dial.

View File

@ -23,7 +23,7 @@ mixin Efl.File requires Efl.Object {
]]
}
values {
f: ptr(const(Eina.File)); [[The handle to the @Eina.File that will be used]]
f: const(Eina.File) @by_ref; [[The handle to the @Eina.File that will be used]]
}
}
@property file {

View File

@ -35,7 +35,7 @@ interface Efl.File_Save {
obligatory).]]
@in key: string; [[The image key in the file (if an Eet one), or $null,
otherwise.]]
@in info: const(ptr(Efl.File_Save_Info)); [[The flags to be used ($null for defaults).]]
@in info: const(Efl.File_Save_Info) @by_ref; [[The flags to be used ($null for defaults).]]
}
return: bool; [[$true on success, $false otherwise]]
}

View File

@ -75,7 +75,7 @@ mixin @beta Efl.Gfx.Color_Class
the third is the text shadow. (Note that the second two only apply
to text parts).
Returns NULL if the color class cannot be fetched.
Returns $NULL if the color class cannot be fetched.
Note: These color values are expected to be premultiplied by $a.]]
}

View File

@ -1529,4 +1529,11 @@ _efl_gfx_path_copy_from(Eo *obj, Efl_Gfx_Path_Data *pd, const Eo *dup_from)
_efl_gfx_path_path_set(obj, pd, from->commands, from->points);
}
EOLIAN static void
_efl_gfx_path_efl_object_destructor(Eo *obj, Efl_Gfx_Path_Data *pd)
{
_efl_gfx_path_reset(obj, pd);
efl_destructor(efl_super(obj, EFL_GFX_PATH_MIXIN));
}
#include "interfaces/efl_gfx_path.eo.c"

View File

@ -1,7 +1,7 @@
import eina_types;
import efl_gfx_types;
mixin @beta Efl.Gfx.Path
mixin @beta Efl.Gfx.Path requires Efl.Object
{
[[EFL graphics path object interface]]
methods {
@ -271,4 +271,7 @@ mixin @beta Efl.Gfx.Path
]]
}
}
implements {
Efl.Object.destructor;
}
}

View File

@ -131,7 +131,7 @@ class @beta Efl.Io.Buffer extends Efl.Object
The returned memory must be freed with eina_binbuf_free().
On failure, for example a read-only backing store was
adopted with @.adopt_readonly, NULL is returned.
adopted with @.adopt_readonly, $NULL is returned.
]]
return: ptr(Eina.Binbuf) @move @no_unused; [[Binbuf]]
}

View File

@ -1,6 +1,6 @@
import eina_types;
interface Efl.Io.Closer {
interface @beta Efl.Io.Closer {
[[Generic interface for objects that can close themselves.
This interface allows external objects to transparently close an

View File

@ -1,6 +1,6 @@
import eina_types;
interface Efl.Io.Reader {
interface @beta Efl.Io.Reader {
[[Generic interface for objects that can read data into a provided memory.
This interface allows external objects to transparently monitor

View File

@ -1,6 +1,6 @@
import eina_types;
interface Efl.Io.Writer {
interface @beta Efl.Io.Writer {
[[Generic interface for objects that can write data from a provided memory.
This interface allows external objects to transparently write

View File

@ -435,7 +435,7 @@ mixin @beta Efl.Access.Object requires Efl.Object
relationship_remove @beta {
[[Removes the relationship between two accessible objects.
If relation_object is NULL function removes all relations
If relation_object is $NULL function removes all relations
of the given type.
]]
params {

View File

@ -19,14 +19,14 @@ enum @beta Efl.Access.Text_Clip_Type
both [[Both clip types]]
}
struct @free(elm_atspi_text_text_attribute_free) Efl.Access.Text_Attribute
struct @beta @free(elm_atspi_text_text_attribute_free) Efl.Access.Text_Attribute
{
[[Text attribute]]
name: string; [[Text attribute name]]
value: string; [[Text attribute value]]
}
struct @free(elm_atspi_text_text_range_free) Efl.Access.Text_Range
struct @beta @free(elm_atspi_text_text_range_free) Efl.Access.Text_Range
{
[[Text range]]
start_offset: int; [[Range start offset]]

View File

@ -1,29 +1,45 @@
enum @beta Efl.Ui.Alert_Popup_Button {
[[Defines the type of the alert button.]]
positive = 0, [[Button having positive meaning. e.g. "Yes"]]
negative, [[Button having negative meaning. e.g. "No"]]
user [[Button having user-defined meaning. e.g. "Cancel"]]
positive = 0, [[Button having positive meaning. E.g. "Yes".]]
negative, [[Button having negative meaning. E.g. "No".]]
user [[Button having user-defined meaning. E.g. "More information".]]
}
struct @beta Efl.Ui.Alert_Popup_Button_Clicked_Event {
[[Information of clicked event]]
button_type: Efl.Ui.Alert_Popup_Button; [[Clicked button type]]
[[Information for @[Efl.Ui.Alert_Popup.button,clicked] event.]]
button_type: Efl.Ui.Alert_Popup_Button; [[Clicked button type.]]
}
class @beta Efl.Ui.Alert_Popup extends Efl.Ui.Popup
{
[[EFL UI Alert Popup class]]
[[A variant of @Efl.Ui.Popup which uses a layout containing a content object and
a variable number of buttons (up to 3 total).
An Alert_Popup is a popup which can be used when an application requires user interaction. It provides
functionality for easily creating button objects on the popup and passing information about
which button has been pressed to the button event callback.
]]
methods {
@property button {
[[This property changes the text and icon for the specified button object.
When set, the Alert_Popup will create a button for the specified type if it does not yet
exist. The button's content and text will be set using the passed values.
Exactly one button may exist for each @Efl.Ui.Alert_Popup_Button type. Repeated calls to
set values for the same button type will overwrite previous values.
By default, no buttons are created. Once a button is added to the Popup using this property
it cannot be removed.
]]
set {
[[Set popup buttons.]]
}
keys {
type: Efl.Ui.Alert_Popup_Button; [[Alert popup button type]]
type: Efl.Ui.Alert_Popup_Button; [[Alert_Popup button type.]]
}
values {
text: string; [[Alert string on button]]
icon: Efl.Object; [[Alert icon on button]]
text: string; [[Text of the specified button type.]]
icon: Efl.Canvas.Object; [[Visual to use as an icon for the specified button type.]]
}
}
}
@ -33,6 +49,6 @@ class @beta Efl.Ui.Alert_Popup extends Efl.Ui.Popup
Efl.Part.part_get;
}
events {
button,clicked: Efl.Ui.Alert_Popup_Button_Clicked_Event; [[Called when alert popup was clicked]]
button,clicked: Efl.Ui.Alert_Popup_Button_Clicked_Event; [[Called when an Alert_Popup button was clicked.]]
}
}

View File

@ -1,6 +1,13 @@
class @beta Efl.Ui.Box_Flow extends Efl.Ui.Box
{
[[A custom layout engine for @Efl.Ui.Box.]]
[[A Flow Box is a customized type of @Efl.Ui.Box. It will fill along the axis selected with
@Efl.Ui.Layout_Orientable.orientation (which defaults to Horizontal), until items will no
longer fit in the available space, at which point it will begin filling items in a new
row/column after the current one.
This is useful if an application wants to e.g., present a group of items and wrap them onto
subsequent lines when the number of items grows too large to fit on the screen.
Adding or removing items in the middle re-arrange the rest of the items as expected.
]]
implements {
Efl.Pack_Layout.layout_update;
}

View File

@ -366,7 +366,7 @@ _efl_ui_collection_efl_object_constructor(Eo *obj, Efl_Ui_Collection_Data *pd EI
_fast_accessor_init(&pd->size_accessor, &pd->items);
if (!elm_widget_theme_klass_get(obj))
elm_widget_theme_klass_set(obj, "item_container");
elm_widget_theme_klass_set(obj, "collection");
o = efl_constructor(efl_super(obj, MY_CLASS));

View File

@ -46,9 +46,9 @@ abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Selectab
@property item_parent {
[[The parent of the item.
This property expresses a tree structure of items. If the parent is NULL the item is added to
This property expresses a tree structure of items. If the parent is $NULL the item is added to
the root level of the content. The item parent can only be set once.
When the object is invalidated, the item parent is set to NULL and still cannot be reset.
When the object is invalidated, the item parent is set to $NULL and still cannot be reset.
]]
values {
parent : Efl.Ui.Item;

View File

@ -1,75 +1,124 @@
parse efl_gfx_hint;
enum @beta Efl.Ui.Popup_Align {
[[Popup alignment type.]]
[[This is the alignment method for positioning Popup widgets.]]
none = 0, [[Popup not aligned.]]
center, [[Popup aligned to center.]]
left, [[Popup aligned to left.]]
right, [[Popup aligned to right.]]
top, [[Popup aligned to top.]]
bottom [[Popup aligned to bottom.]]
center, [[Popup is aligned to the center of its anchor object.]]
left, [[Popup's left edge is aligned to the left side of its anchor object.]]
right, [[Popup's right edge is aligned to the right side of its anchor object.]]
top, [[Popup's top is aligned to the top of its anchor object.]]
bottom [[Popup's bottom is aligned to the bottom of its anchor object.]]
}
class @beta Efl.Ui.Popup extends Efl.Ui.Layout_Base implements Efl.Content, Efl.Ui.Focus.Layer,
Efl.Ui.Widget_Scrollable_Content
{
[[EFL UI popup class]]
[[A styled container widget which overlays a window's contents.
The Popup widget is a theme-capable container which can be used for various purposes.
Regular contents can be set using the @Efl.Content interface, or basic scrollable contents
can be set through the @Efl.Ui.Widget_Scrollable_Content mixin API. For contents which
should be scrollable but require more fine-grained tuning, it may be necessary for users
to set up and provide their own scroller object such as @Efl.Ui.Scroller.
A Popup widget will create an overlay for the window contents. This overlay is an
@Efl.Ui.Popup_Part_Backwall object, which provides functionality for passing events
through to the main window while the Popup is active as well as the ability to set
background images for the Popup.
By default, a Popup is positioned by the user through the @Efl.Gfx.Entity.position property.
This behavior can be altered by using the @.align and @.anchor properties. Setting the
@Efl.Gfx.Entity.position property directly will unset both the @.align and @.anchor properties,
and vice versa.
By default, a Popup will size itself based on the minimum size of its contents through the
@Efl.Gfx.Hint interface. A Popup will never size itself smaller than the minimum size of its contents,
but by manually setting the @Efl.Gfx.Entity.size property or the @Efl.Gfx.Hint.hint_size_min property,
a larger size can be specified.
Users can set a given Popup widget to close automatically after a specified time using the @.closing_timeout
property.
For a Popup with a more specialized purpose, see @Efl.Ui.Alert_Popup.
]]
methods {
@property align {
[[Popup alignment.]]
[[The align property specifies a Popup's current positioning relative to its anchor.
When set, this property will override any user-provided value for
the widget's @Efl.Gfx.Entity.position property.
]]
set {
}
get {
}
values {
type: Efl.Ui.Popup_Align; [[Alignment type.]]
type: Efl.Ui.Popup_Align; [[Alignment of the Popup relative to its anchor.
The default is @Efl.Ui.Popup_Align.none.]]
}
}
@property closing_timeout {
[[Set the timeout seconds.
After timeout seconds, popup will be deleted automatically.
[[The closing_timeout property is the time after which the Popup widget will be automatically deleted.
The timer is initiated at the time when the popup is shown. If the value is changed
prior to the timer expiring, the existing timer will be deleted. If the new value is greater than $0,
a new timer will be created.
]]
set {
}
get {
}
values {
time: double; [[Timeout in seconds.]]
time: double; [[If greater than $0, the Popup will close automatically after the value in seconds.
The default is to not automatically delete the Popup.]]
}
}
@property anchor {
[[Anchor object which sets this popup's position.
If anchor object is moved or parent window is resized, the popup moves to the new position.
If anchor object is set to NULL, the popup stops following the anchor object.
When the popup is moved by using @Efl.Gfx.Entity.position.set, $anchor is set NULL.
[[The anchor object is the reference object for positioning a Popup
using the @.align and @.align_priority properties.
A Popup will recalculate its alignment relative to its anchor and change its position when:
- the anchor object is moved (unless the anchor is a window)
- the anchor object is resized
- the Popup is resized
- the parent window is resized
If @.anchor.get returns $NULL, the anchor is the parent window of the Popup.
If the anchor object is set to $NULL, the Popup will no longer recalculate its alignment or change
its position under any circumstance.
If the Popup is moved by using @Efl.Gfx.Entity.position.set, $anchor is set $NULL.
]]
set {
}
get {
}
values {
anchor: Efl.Canvas.Object; [[The object which popup is following.]]
anchor: Efl.Canvas.Object; [[The object which Popup is following. By default this is $NULL.]]
}
}
@property align_priority {
[[Prioritized popup alignment.
In contrast to the @.align property, each alignment is tried in turn until one is found which allows
the popup to be placed in the exact requested position relative to the @.anchor.
[[This is the priority in which alignments will be tested using the anchor object if the value of @.align
is determined to be invalid. If a given alignment would result in the popup being partially or fully
outside the visible area of the window, it is deemed invalid, and the next alignment is tested
until either the priority list is exhausted or a usable alignment is found.
An alignment will also be deemed invalid if the popup occludes its anchor object,
except if @Efl.Ui.Popup_Align.center is specified.
]]
set {
}
get {
}
values {
first: Efl.Ui.Popup_Align; [[First alignment.]]
second: Efl.Ui.Popup_Align; [[Second alignment.]]
third: Efl.Ui.Popup_Align; [[Third alignment.]]
fourth: Efl.Ui.Popup_Align; [[Fourth alignment.]]
fifth: Efl.Ui.Popup_Align; [[Fifth alignment.]]
first: Efl.Ui.Popup_Align; [[First alignment. The default is @Efl.Ui.Popup_Align.top.]]
second: Efl.Ui.Popup_Align; [[Second alignment. The default is @Efl.Ui.Popup_Align.left.]]
third: Efl.Ui.Popup_Align; [[Third alignment. The default is @Efl.Ui.Popup_Align.right.]]
fourth: Efl.Ui.Popup_Align; [[Fourth alignment. The default is @Efl.Ui.Popup_Align.bottom.]]
fifth: Efl.Ui.Popup_Align; [[Fifth alignment. The default is @Efl.Ui.Popup_Align.center.]]
}
}
}
parts {
backwall: Efl.Ui.Popup_Part_Backwall; [[A backwall behind the popup.]]
backwall: Efl.Ui.Popup_Part_Backwall; [[A backwall behind the Popup.]]
}
implements {
Efl.Object.constructor;
@ -84,7 +133,7 @@ class @beta Efl.Ui.Popup extends Efl.Ui.Layout_Base implements Efl.Content, Efl.
Efl.Part.part_get;
}
events {
backwall,clicked: void; [[This is called whenever the user clicks back wall of popup.]]
timeout: void; [[This is called when popup times out.]]
backwall,clicked: void; [[This is called whenever the user clicks the backwall part of the Popup.]]
timeout: void; [[This is called when Popup times out.]]
}
}

View File

@ -1,26 +1,31 @@
class @beta Efl.Ui.Popup_Part_Backwall extends Efl.Ui.Layout_Part implements Efl.File
{
[[Efl UI Popup internal part backwall class]]
[[A Popup backwall is the background object for an @Efl.Ui.Popup widget. It can be returned
from a given Popup widget by using the @Efl.Part API to fetch the "backwall" part.
This object provides functionality for determining the look and interaction methods
of a Popup's background.
If a Popup should allow input events to reach the objects behind the Popup,
@.repeat_events can be enabled.
To set an image to be used as a background for the Popup, the @Efl.File API can
be used directly on the backwall object.
]]
data: null;
methods {
@property repeat_events {
[[If this property is set to $true, input events will be able to reach objects
below the Popup. This allows for e.g., a click to activate a widget below the Popup
while the Popup is active.
]]
set {
[[Set whether backwall is to repeat events.
If $repeat is $true, it will make events on $obj to also be
repeated for the next lower object in the objects' stack (see
@Efl.Gfx.Stack.below).
If $repeat is $false, events occurring on $obj will be
processed only on it.
]]
}
get {
[[Determine whether backwall is set to repeat events.]]
}
values {
repeat: bool; [[Whether $obj is to repeat events ($true) or
not ($false).]]
repeat: bool; [[Whether to repeat events to objects below the Popup. The default is $false.]]
}
}
}

View File

@ -23,7 +23,7 @@ typedef struct {
} Vis_Segment;
static Efl_Ui_Position_Manager_Size_Batch_Result
_batch_request_size(Api_Callbacks cb , int start_id, int len, Eina_Bool cache, void *data)
_batch_request_size(Api_Callbacks cb , int start_id, int end_id, int len, Eina_Bool cache, void *data)
{
Efl_Ui_Position_Manager_Size_Batch_Result res;
@ -34,28 +34,28 @@ _batch_request_size(Api_Callbacks cb , int start_id, int len, Eina_Bool cache, v
Efl_Ui_Position_Manager_Size_Call_Config conf;
conf.cache_request = cache;
conf.range.start_id = start_id;
conf.range.end_id = start_id + len;
conf.range.end_id = MIN(start_id + len, end_id);
res = cb.size.access(cb.size.data, conf, slice);
return res;
}
#define BATCH_ACCESS_SIZE(cb, start_id, len, cache, data) \
#define BATCH_ACCESS_SIZE(cb, start_id, end_id, len, cache, data) \
do { \
size_result = _batch_request_size((cb), (start_id), (len), (cache), (data)); \
size_result = _batch_request_size((cb), (start_id), (end_id), (len), (cache), (data)); \
EINA_SAFETY_ON_FALSE_RETURN(size_result.filled_items > 0); \
} while(0);
#define BATCH_ACCESS_SIZE_VAL(cb, start_id, len, cache, data, V) \
#define BATCH_ACCESS_SIZE_VAL(cb, start_id, end_id, len, cache, data, V) \
do { \
size_result = _batch_request_size((cb), (start_id), (len), (cache), (data)); \
size_result = _batch_request_size((cb), (start_id), (end_id), (len), (cache), (data)); \
EINA_SAFETY_ON_FALSE_RETURN_VAL(size_result.filled_items > 0, V); \
} while(0);
static Efl_Ui_Position_Manager_Object_Batch_Result
_batch_request_objects(Api_Callbacks cb , int start_id, int len, void *data)
_batch_request_objects(Api_Callbacks cb , int start_id, int end_id, int len, void *data)
{
Efl_Ui_Position_Manager_Object_Batch_Result res;
@ -65,22 +65,22 @@ _batch_request_objects(Api_Callbacks cb , int start_id, int len, void *data)
Efl_Ui_Position_Manager_Request_Range range;
range.start_id = start_id;
range.end_id = start_id + len;
range.end_id = MIN(start_id + len, end_id);
res = cb.object.access(cb.object.data, range, slice);
return res;
}
#define BATCH_ACCESS_OBJECT(cb, start_id, len, data) \
#define BATCH_ACCESS_OBJECT(cb, start_id, end_id, len, data) \
do { \
object_result = _batch_request_objects((cb), (start_id), (len), (data)); \
object_result = _batch_request_objects((cb), (start_id), (end_id), (len), (data)); \
EINA_SAFETY_ON_FALSE_RETURN(object_result.filled_items > 0); \
} while(0);
#define BATCH_ACCESS_OBJECT_VAL(cb, start_id, len, data, v) \
#define BATCH_ACCESS_OBJECT_VAL(cb, start_id, end_id, len, data, v) \
do { \
object_result = _batch_request_objects((cb), (start_id), (len), (data)); \
object_result = _batch_request_objects((cb), (start_id), (end_id), (len), (data)); \
EINA_SAFETY_ON_FALSE_RETURN_VAL(object_result.filled_items > 0, v); \
} while(0);
@ -100,7 +100,7 @@ vis_change_segment(Api_Callbacks cb, int a, int b, Eina_Bool flag)
if (buffer_id == 0)
{
BATCH_ACCESS_OBJECT(cb, i, len, data);
BATCH_ACCESS_OBJECT(cb, i, MAX(a,b), len, data);
}
ent = data[buffer_id].entity;
if (ent && !flag && (efl_ui_focus_object_focus_get(ent) || efl_ui_focus_object_child_focus_get(ent)))

View File

@ -118,7 +118,7 @@ interface @beta Efl.Ui.Position_Manager.Data_Access_V1 {
values {
obj_access : Efl.Ui.Position_Manager.Object_Batch_Callback; [[Function callback for canvas objects, even if
the start_id is valid, the returned objects
may be NULL.]]
may be $NULL.]]
size_access : Efl.Ui.Position_Manager.Size_Batch_Callback; [[Function callback for the size, returned values
are always valid, but might be changed later on.
]]

View File

@ -70,7 +70,7 @@ _group_cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data *pd)
if (buffer_id == 0)
{
BATCH_ACCESS_SIZE(pd->callbacks, i, MIN(len, pd->size - i), EINA_TRUE, size_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, i, pd->size, MIN(len, pd->size - i), EINA_TRUE, size_buffer);
}
if (size_buffer[buffer_id].depth_leader)
@ -266,8 +266,8 @@ _position_items_vertical(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Data
int buffer_id = (i-ctx->new.start_id) % len;
if (buffer_id == 0)
{
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, len, obj_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, i, ctx->new.end_id, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, ctx->new.end_id, len, obj_buffer);
if (i == ctx->new.start_id)
{
@ -333,8 +333,8 @@ _position_items_horizontal(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_Grid_Dat
int buffer_id = (i-ctx->new.start_id) % len;
if (buffer_id == 0)
{
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, len, obj_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, i, ctx->new.end_id, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, ctx->new.end_id, len, obj_buffer);
if (i == ctx->new.start_id)
{
@ -593,7 +593,7 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_item_added(Eo *obj,
efl_gfx_entity_visible_set(subobj, EINA_FALSE);
_group_cache_invalidate(obj, pd);
BATCH_ACCESS_SIZE(pd->callbacks, added_index, 1, EINA_TRUE, size_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, added_index, added_index + 1, 1, EINA_TRUE, size_buffer);
_update_min_size(obj, pd, added_index, size_buffer[0].size);
_flush_min_size(obj, pd);
_schedule_recalc_abs_size(obj, pd);
@ -624,7 +624,7 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_item_size_changed(E
int buffer_id = (i-start_id) % len;
if (buffer_id == 0)
{
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_TRUE, size_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, i, end_id + 1, len, EINA_TRUE, size_buffer);
}
_update_min_size(obj, pd, i, size_buffer[buffer_id].size);
}
@ -662,7 +662,7 @@ _efl_ui_position_manager_grid_efl_ui_position_manager_entity_position_single_ite
if (!pd->size) return EINA_RECT(0, 0, 0, 0);
if (pd->max_min_size.w <= 0 || pd->max_min_size.h <= 0) return EINA_RECT(0, 0, 0, 0);
BATCH_ACCESS_SIZE_VAL(pd->callbacks, idx, 1, EINA_TRUE, size_buffer, EINA_RECT_EMPTY());
BATCH_ACCESS_SIZE_VAL(pd->callbacks, idx, idx + 1, 1, EINA_TRUE, size_buffer, EINA_RECT_EMPTY());
_size_cache_require(obj, pd);
_flush_abs_size(obj, pd);

View File

@ -66,7 +66,7 @@ cache_require(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd)
if (buffer_id == 0)
{
BATCH_ACCESS_SIZE(pd->callbacks, i, MIN(len, pd->size - i), EINA_TRUE, size_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, i, pd->size, MIN(len, pd->size - i), EINA_TRUE, size_buffer);
}
size = size_buffer[buffer_id].size;
@ -192,8 +192,8 @@ _position_items(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Vis_
if (buffer_id == 0)
{
BATCH_ACCESS_SIZE(pd->callbacks, i, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, len, obj_buffer);
BATCH_ACCESS_SIZE(pd->callbacks, i, new.end_id, len, EINA_FALSE, size_buffer);
BATCH_ACCESS_OBJECT(pd->callbacks, i, new.end_id, len, obj_buffer);
if (i == new.start_id)
{
@ -238,8 +238,14 @@ _position_items(Eo *obj EINA_UNUSED, Efl_Ui_Position_Manager_List_Data *pd, Vis_
if (ent)
{
const char *signal;
efl_gfx_entity_visible_set(ent, EINA_TRUE);
efl_gfx_entity_geometry_set(ent, geom);
if (i % 2 == 0)
signal = "efl,state,even";
else
signal = "efl,state,odd";
efl_layout_signal_emit(ent, signal, "efl");
}
if (pd->dir == EFL_UI_LAYOUT_ORIENTATION_VERTICAL)
geom.y += size.h;
@ -427,7 +433,7 @@ _efl_ui_position_manager_list_efl_ui_position_manager_entity_position_single_ite
geom = pd->viewport;
BATCH_ACCESS_SIZE_VAL(pd->callbacks, idx, 1, EINA_FALSE, size_buffer, EINA_RECT_EMPTY());
BATCH_ACCESS_SIZE_VAL(pd->callbacks, idx, idx + 1, 1, EINA_FALSE, size_buffer, EINA_RECT_EMPTY());
size = size_buffer[0].size;

View File

@ -12,7 +12,7 @@ class @beta Efl.Ui.Scroll.Manager extends Efl.Object implements
This property is protected as it is meant for scrollable object
implementations only, to set and access the internal pan object.
If pan is set to NULL, scrolling does not work.
If pan is set to $NULL, scrolling does not work.
]]
set {
}

View File

@ -91,7 +91,7 @@ class @beta Efl.Ui.Spotlight.Container extends Efl.Ui.Layout_Base implements Efl
]]
params {
deletion_on_transition_end : bool; [[If $true, then the object will be deleted before resolving the future,
and a NULL pointer is the value of the future.
and a $NULL pointer is the value of the future.
$false if no operation should be applied to it.]]
}
return : future<Efl.Gfx.Entity>; [[This Future gets resolved when any transition animation finishes and the

View File

@ -40,7 +40,7 @@ class @beta Efl.Ui.Tags extends Efl.Ui.Layout_Base
get {
}
values {
items: const(array<string>); [[The array of items, or NULL if none.]]
items: const(array<string>); [[The array of items, or $NULL if none.]]
}
}
}

View File

@ -359,7 +359,7 @@ class @beta Efl.Ui.Text extends Efl.Ui.Layout_Base implements Efl.Input.Clickabl
}
events {
changed: void; [[Called when entry changes]]
/* can be NULL, tag nullable once Eolian supports it */
/* can be $NULL, tag nullable once Eolian supports it */
changed,user: Efl.Ui.Text_Change_Info;
[[The text object has changed due to user interaction]]
validate: Elm.Validate_Content; [[Called when validating]]

View File

@ -4788,27 +4788,24 @@ elm_widget_tree_dot_dump(const Evas_Object *top,
EOLIAN static Eo *
_efl_ui_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
{
Eina_Bool parent_is_widget = EINA_FALSE;
sd->on_create = EINA_TRUE;
sd->window = efl_provider_find(efl_parent_get(obj), EFL_UI_WIN_CLASS);
if (!efl_isa(obj, EFL_UI_WIN_CLASS))
{
Eo *parent = efl_parent_get(obj);
parent_is_widget = efl_isa(parent, EFL_UI_WIDGET_CLASS);
if (!parent_is_widget)
if (!efl_isa(parent, EFL_UI_WIDGET_CLASS))
{
ERR("You passed a wrong parent parameter (%p %s). "
"Elementary widget's parent should be an elementary widget.",
parent, evas_object_type_get(parent));
}
ELM_WIDGET_DATA_GET(parent, parent_sd);
if (parent_sd)
sd->shared_win_data = parent_sd->shared_win_data;
else
sd->shared_win_data = efl_ui_win_shared_data_get(obj);
efl_ui_widget_sub_object_add(parent, obj);
{
ELM_WIDGET_DATA_GET(parent, parent_sd);
sd->shared_win_data = parent_sd->shared_win_data;
efl_ui_widget_sub_object_add(parent, obj);
}
}
else
{
@ -4825,11 +4822,8 @@ _efl_ui_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UN
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_UNKNOWN);
if (!sd->shared_win_data)
{
if (sd->window && parent_is_widget)
EINA_SAFETY_ON_NULL_RETURN_VAL(sd->shared_win_data, NULL);
}
if (!elm_widget_is_legacy(obj))
EINA_SAFETY_ON_NULL_RETURN_VAL(sd->shared_win_data, NULL);
return obj;
}
@ -5160,7 +5154,7 @@ _efl_ui_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd,
/* Legacy APIs */
EAPI void
elm_widget_on_show_region_hook_set(Eo *obj, void *data, Efl_Ui_Scrollable_On_Show_Region func, Eina_Free_Cb func_free_cb)
elm_widget_on_show_region_hook_set(Eo *obj, void *data, Elm_Widget_On_Show_Region_Cb func, Eina_Free_Cb func_free_cb)
{
ELM_WIDGET_DATA_GET(obj, sd);

View File

@ -1,11 +1,3 @@
function @beta Efl.Ui.Scrollable_On_Show_Region {
[[Function pointer for on show region hook]]
params {
@in obj: Efl.Canvas.Object; [[Canvas object]]
@in region: Eina.Rect; [[Showed region]]
}
};
struct Efl.Ui.Widget_Focus_State {
[[All relevant fields needed for the current state of focus registration
@since 1.22

View File

@ -11,12 +11,6 @@ typedef Eo Efl_Ui_Widget;
#ifndef _EFL_UI_WIDGET_EO_TYPES
#define _EFL_UI_WIDGET_EO_TYPES
/** Function pointer for on show region hook
*
* @ingroup Efl_Ui
*/
typedef void (*Efl_Ui_Scrollable_On_Show_Region)(void *data, Efl_Canvas_Object *obj, Eina_Rect region);
/** All relevant fields needed for the current state of focus registeration
*
* @ingroup Efl_Ui

View File

@ -1,13 +1,18 @@
import eina_types;
parse efl_text_format;
mixin @beta Efl.Ui.Widget_Scrollable_Content requires Efl.Object
{
[[Efl widget scrollable content mixin
This can be used to provide scrollable contents and text for widgets.
This can be used to provide scrollable contents and text for widgets. When a scrollable
text or content is set, this mixin will create and manage an internal scroller object which
will be the container of that text or content.
Widgets can set the "__efl_scrollable_content_scroller_style" key data during
their constructor to apply a style to the internal scroller widget.
Only a single content or text can be set at any given time. Setting @.scrollable_content
will unset @.scrollable_text and vice versa.
@since 1.23
]]
c_prefix: efl_ui_widget;
event_prefix: efl_ui_widget_scrollable_content;
@ -22,11 +27,13 @@ mixin @beta Efl.Ui.Widget_Scrollable_Content requires Efl.Object
this method returns $true.
In the case that this returns $true, it's likely that the widget should be completing
its internal sizing calculations from the optimal_size,calc callback using
its internal sizing calculations from the @[Efl.Ui.Widget_Scrollable_Content.optimal_size,calc] callback using
`efl_canvas_group_calculate(efl_super(ev->object, EFL_UI_WIDGET_SCROLLABLE_CONTENT_MIXIN));`
efl_canvas_group_calculate(efl_super(ev->object, EFL_UI_WIDGET_SCROLLABLE_CONTENT_MIXIN));
in order to skip the scrollable sizing calc.
@since 1.23
]]
get {}
values {
@ -35,6 +42,8 @@ mixin @beta Efl.Ui.Widget_Scrollable_Content requires Efl.Object
}
@property scrollable_content {
[[This is the content which will be placed in the internal scroller.
@since 1.23
]]
set {
return: bool; [[True on success]]
@ -47,10 +56,13 @@ mixin @beta Efl.Ui.Widget_Scrollable_Content requires Efl.Object
@property scrollable_text {
set {
[[Sets the text string to be displayed by the given text object.
The text will be scrollable depending on its size relative to the
The text will use @Efl.Text_Format_Wrap.mixed wrapping,
and it will be scrollable depending on its size relative to the
object's geometry.
See also @.scrollable_text.get.
@since 1.23
]]
}
get {
@ -60,6 +72,8 @@ mixin @beta Efl.Ui.Widget_Scrollable_Content requires Efl.Object
Do not free() the return value.
See also @.scrollable_text.set.
@since 1.23
]]
}
values {

View File

@ -36,7 +36,7 @@ class @beta Elm.Code_Widget extends Efl.Ui.Layout
@property font {
set {
[[Set the font that this widget uses, the font should be a monospaced scalable font.
Passing NULL will load the default system monospaced font.]]
Passing $NULL will load the default system monospaced font.]]
}
get {
[[Get the font currently in use.

View File

@ -303,6 +303,8 @@ typedef Eina_Bool (*Elm_Widget_Del_Pre_Cb)(void *data);
typedef void (*Elm_Widget_Item_Signal_Cb)(void *data, Elm_Object_Item *item, const char *emission, const char *source);
typedef void (*Elm_Access_On_Highlight_Cb)(void *data);
typedef void (*Elm_Widget_On_Show_Region_Cb)(void *data, Evas_Object *obj, Eina_Rect region);
#include "efl_ui_widget.eo.h"
#include "elm_widget_item_container_eo.h"
@ -359,7 +361,7 @@ typedef struct _Elm_Widget_Smart_Data
* handling the request of showing a specific region from an inner
* widget (mainly issued by entries, on cursor moving) */
void *on_show_region_data;
Efl_Ui_Scrollable_On_Show_Region on_show_region;
Elm_Widget_On_Show_Region_Cb on_show_region;
Eina_Free_Cb on_show_region_data_free;
Elm_Focus_Move_Policy focus_move_policy;
@ -587,7 +589,7 @@ EAPI Eina_Bool elm_widget_api_check(int ver);
EAPI Eina_Bool elm_widget_access(Evas_Object *obj, Eina_Bool is_access);
EAPI Eina_Error elm_widget_theme(Evas_Object *obj);
EAPI void elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force);
EAPI void elm_widget_on_show_region_hook_set(Evas_Object *obj, void *data, Efl_Ui_Scrollable_On_Show_Region func, Eina_Free_Cb data_free);
EAPI void elm_widget_on_show_region_hook_set(Evas_Object *obj, void *data, Elm_Widget_On_Show_Region_Cb func, Eina_Free_Cb data_free);
EAPI Eina_Bool elm_widget_sub_object_parent_add(Evas_Object *sobj);
EAPI Eina_Bool elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj);
EAPI Eina_Bool elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj);

View File

@ -205,7 +205,7 @@ abstract Efl.Object
The object from the provider will then be returned.
The base implementation calls the provider_find function on the object parent,
and returns its result. If no parent is present NULL is returned.
and returns its result. If no parent is present $NULL is returned.
Each implementation has to support this function by overriding
it and returning itself if the interface matches the parameter.
If this is not done the class cannot be found up in the object tree.
@ -330,7 +330,7 @@ abstract Efl.Object
by inserting a handler at the right position in the stack of event handler on the object that
emit the event.]]
params {
@in desc: ptr(const(Efl.Event_Description)); [[The description of the event to listen to]]
@in desc: const(Efl.Event_Description) @by_ref; [[The description of the event to listen to]]
@in priority: Efl.Callback_Priority; [[The priority at which to insert the event forwarder handler
in the existing list of handler on the source of event object. The lower the number, the higher
the priority. As a shortcut @Efl.Callback_Priority_Before,
@ -342,7 +342,7 @@ abstract Efl.Object
event_callback_forwarder_del {
[[Remove an event callback forwarder for a specified event and object.]]
params {
@in desc: ptr(const(Efl.Event_Description)); [[The description of the event to listen to]]
@in desc: const(Efl.Event_Description) @by_ref; [[The description of the event to listen to]]
@in new_obj: Efl.Object; [[The object to emit events from]]
}
}

View File

@ -107,7 +107,7 @@ database_type_to_str(const Eolian_Type *tp,
|| tp->type == EOLIAN_TYPE_CLASS
|| tp->type == EOLIAN_TYPE_VOID)
&& tp->is_const
&& ((ctype != EOLIAN_C_TYPE_RETURN) || database_type_is_ownable(NULL, tp, EINA_FALSE)))
&& ((ctype != EOLIAN_C_TYPE_RETURN) || by_ref || database_type_is_ownable(NULL, tp, EINA_FALSE)))
{
eina_strbuf_append(buf, "const ");
}

View File

@ -229,8 +229,8 @@ _validate_by_ref(Eolian_Type *tp, Eina_Bool by_ref, Eina_Bool move)
if (tp->btype == EOLIAN_TYPE_BUILTIN_FUTURE)
return EINA_TRUE;
/* not marked @move; just validate */
if (!move)
/* not marked @move, or marked @by_ref; just validate */
if (!move || by_ref)
return EINA_TRUE;
/* marked @move, not pointer-like or otherwise ownable, error */
@ -260,6 +260,11 @@ _validate_type(Validate_State *vals, Eolian_Type *tp)
if (tp->is_ptr)
{
if (vals->stable)
{
_eo_parser_log(&tp->base, "ptr() used in stable API");
return EINA_FALSE;
}
tp->is_ptr = EINA_FALSE;
Eina_Bool still_ownable = database_type_is_ownable(src, tp, EINA_FALSE);
tp->is_ptr = EINA_TRUE;
@ -1472,7 +1477,7 @@ database_validate(const Eolian_Unit *src)
EINA_FALSE,
EINA_TRUE,
!!getenv("EOLIAN_CLASS_UNIMPLEMENTED_WARN"),
!!getenv("EOLIAN_CLASS_UNIMPLEMENTED_BETA_WARN"),
!!getenv("EOLIAN_CLASS_UNIMPLEMENTED_BETA_WARN")
};
/* do an initial pass to refill inherits */

View File

@ -1277,6 +1277,26 @@ struct klass_def
|| lhs.parts < rhs.parts;
}
friend inline bool operator==(klass_def const& lhs, klass_name const& rhs)
{
return lhs.namespaces == rhs.namespaces
&& lhs.eolian_name == rhs.eolian_name
&& lhs.type == rhs.type;
}
friend inline bool operator==(klass_name const& lhs, klass_def const& rhs)
{
return rhs == lhs;
}
friend inline bool operator!=(klass_def const& lhs, klass_name const& rhs)
{
return !(lhs == rhs);
}
friend inline bool operator!=(klass_name const& lhs, klass_def const& rhs)
{
return !(rhs == lhs);
}
klass_def(std::string eolian_name, std::string cxx_name, std::string filename
, documentation_def documentation
, std::vector<std::string> namespaces

View File

@ -14,7 +14,7 @@ class @beta Efl.Canvas.Animation_Rotate extends Efl.Canvas.Animation
from_degree: double; [[Rotation degree when animation starts]]
to_degree: double; [[Rotation degree when animation ends]]
pivot: Efl.Canvas.Object; [[Pivot object for the center point.
If the pivot object is NULL, then the object is rotated on itself.]]
If the pivot object is $NULL, then the object is rotated on itself.]]
cx: double; [[X relative coordinate of the center point.
The left end is 0.0 and the right end is 1.0 (the center is 0.5).]]
cy: double; [[Y relative coordinate of the center point.

View File

@ -15,7 +15,7 @@ class @beta Efl.Canvas.Animation_Scale extends Efl.Canvas.Animation
from_scale_y: double; [[Scale factor along y axis when animation starts]]
to_scale_x: double; [[Scale factor along x axis when animation ends]]
to_scale_y: double; [[Scale factor along y axis when animation ends]]
pivot: Efl.Canvas.Object; [[Pivot object for the center point. If the pivot object is NULL, then the object
pivot: Efl.Canvas.Object; [[Pivot object for the center point. If the pivot object is $NULL, then the object
is scaled on itself.]]
cx: double; [[X relative coordinate of the center point. The left end is 0.0 and the right end is 1.0
(the center is 0.5).]]

View File

@ -289,7 +289,8 @@ _efl_canvas_vg_object_efl_file_load(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd)
Evas_Object_Protected_Data *obj;
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
pd->vg_entry = evas_cache_vg_entry_create(file, key,
pd->vg_entry = evas_cache_vg_entry_create(evas_object_evas_get(eo_obj),
file, key,
obj->cur->geometry.w,
obj->cur->geometry.h);
evas_object_change(eo_obj, obj);

View File

@ -18,6 +18,7 @@ typedef struct _Vg_Cache
typedef struct _Vg_Cache_Entry
{
Evas *evas;
char *hash_key;
const Eina_File *file;
Eina_Stringshare *key;
@ -124,7 +125,7 @@ struct _Efl_Canvas_Vg_Interpolation
void evas_cache_vg_init(void);
void evas_cache_vg_shutdown(void);
Vg_Cache_Entry* evas_cache_vg_entry_resize(Vg_Cache_Entry *entry, int w, int h);
Vg_Cache_Entry* evas_cache_vg_entry_create(const Eina_File *file, const char *key, int w, int h);
Vg_Cache_Entry* evas_cache_vg_entry_create(Evas *evas, const Eina_File *file, const char *key, int w, int h);
Efl_VG* evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry, unsigned int frame_num);
void evas_cache_vg_entry_del(Vg_Cache_Entry *vg_entry);
Vg_File_Data * evas_cache_vg_file_open(const Eina_File *file, const char *key);

View File

@ -365,11 +365,12 @@ evas_cache_vg_file_open(const Eina_File *file, const char *key)
Vg_Cache_Entry*
evas_cache_vg_entry_resize(Vg_Cache_Entry *vg_entry, int w, int h)
{
return evas_cache_vg_entry_create(vg_entry->file, vg_entry->key, w, h);
return evas_cache_vg_entry_create(vg_entry->evas, vg_entry->file, vg_entry->key, w, h);
}
Vg_Cache_Entry*
evas_cache_vg_entry_create(const Eina_File *file,
evas_cache_vg_entry_create(Evas *evas,
const Eina_File *file,
const char *key,
int w, int h)
{
@ -381,7 +382,7 @@ evas_cache_vg_entry_create(const Eina_File *file,
//TODO: zero-sized entry is useless. how to skip it?
hash_key = eina_strbuf_new();
eina_strbuf_append_printf(hash_key, "%p/%s/%d/%d", file, key, w, h);
eina_strbuf_append_printf(hash_key, "%p/%p/%s/%d/%d", evas, file, key, w, h);
vg_entry = eina_hash_find(vg_cache->vg_entry_hash, eina_strbuf_string_get(hash_key));
if (!vg_entry)
{
@ -396,6 +397,7 @@ evas_cache_vg_entry_create(const Eina_File *file,
vg_entry->key = eina_stringshare_add(key);
vg_entry->w = w;
vg_entry->h = h;
vg_entry->evas = evas;
vg_entry->hash_key = eina_strbuf_string_steal(hash_key);
eina_hash_direct_add(vg_cache->vg_entry_hash, vg_entry->hash_key, vg_entry);
}

View File

@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
namespace TestSuite
{
@ -533,4 +534,91 @@ class TestObjectDeletion
}
}
class TestProtectedInterfaceMembers
{
private class MyObject : Dummy.TestObject
{
public MyObject(Efl.Object parent = null) : base(parent)
{
}
protected override int MethodProtected(int x)
{
return x * x;
}
}
public static void test_protected_interface_in_generated_class_called_from_c()
{
var obj = new Dummy.TestObject();
Test.AssertEquals(obj.CallMethodProtected(42), -42);
}
public static void test_protected_interface_in_inherited_class_called_from_c()
{
var obj = new MyObject();
Test.AssertEquals(obj.CallMethodProtected(42), 42 * 42);
}
public static void test_interface_skipped_protected()
{
var type = typeof(Dummy.ITestIface);
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
// Fully protected property
Test.AssertNull(methods.SingleOrDefault(m => m.Name == "GetProtectedProp"));
Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetProtectedProp"));
// Partially protected property
Test.AssertNotNull(methods.SingleOrDefault(m => m.Name == "GetPublicGetterPrivateSetter"));
Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetPublicGetterPrivateSetter"));
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
Test.AssertNull(properties.SingleOrDefault(m => m.Name == "ProtectedProp"));
Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter"));
}
public static void test_interface_skipped_protected_in_implementation()
{
var type = typeof(Dummy.TestObject);
// Fully protected property
var protected_methods = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(m => m.IsFamily);
Test.AssertNotNull(protected_methods.SingleOrDefault(m => m.Name == "GetProtectedProp"));
Test.AssertNotNull(protected_methods.SingleOrDefault(m => m.Name == "SetProtectedProp"));
// Partially protected property
var public_methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
Test.AssertNotNull(public_methods.SingleOrDefault(m => m.Name == "GetPublicGetterPrivateSetter"));
Test.AssertNotNull(protected_methods.SingleOrDefault(m => m.Name == "SetPublicGetterPrivateSetter"));
var protected_properties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
var prop = protected_properties.SingleOrDefault(m => m.Name == "ProtectedProp");
Test.AssertNotNull(prop);
Test.Assert(prop.GetMethod.IsFamily);
Test.Assert(prop.SetMethod.IsFamily);
var public_properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
prop = public_properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter");
Test.AssertNotNull(prop);
Test.Assert(prop.GetMethod.IsPublic);
Test.Assert(prop.SetMethod.IsFamily);
}
}
class TestStaticInterfaceMembers
{
public static void test_interface_static_member()
{
var iface = typeof(Dummy.ITestIface);
var properties = iface.GetProperties(BindingFlags.Public | BindingFlags.Instance);
Test.AssertNull(properties.SingleOrDefault(p => p.Name == "StaticProp"));
var implementation = typeof(Dummy.TestObject);
properties = implementation.GetProperties(BindingFlags.Public | BindingFlags.Static);
Test.AssertNotNull(properties.SingleOrDefault(p => p.Name == "StaticProp"));
}
}
}

View File

@ -39,6 +39,8 @@ class TestEoEvents
Test.Assert(listener.called);
Test.Assert(listener.correct_sender);
Test.AssertEquals("loop_called", loop.GetName());
loop.IdleEvent -= listener.callback;
}
public static void event_with_string_payload()

View File

@ -16,6 +16,16 @@ class TestStrBuf
Test.AssertEquals("Here's Johnny!", buf.Steal());
}
public static void test_tostring()
{
Eina.Strbuf buf = new Eina.Strbuf();
buf.Append("Hello");
buf.Append(' ');
buf.Append("World!");
Test.AssertEquals("Hello World!", buf.ToString());
}
public static void test_eolian()
{
var obj = new Dummy.TestObject();

View File

@ -1,5 +1,16 @@
// Include file for interfaces .eo.c files
#define DUMMY_TEST_IFACE_PROTECTED
#include "libefl_mono_native_test.h"
void _dummy_test_iface_static_prop_set(int data EINA_UNUSED)
{
}
int _dummy_test_iface_static_prop_get()
{
return -1;
}
#include "dummy_test_iface.eo.c"
#include "dummy_inherit_iface.eo.c"

View File

@ -10,6 +10,45 @@ interface Dummy.Test_Iface
data: int;
}
}
method_protected @protected @const {
params {
@in x: int;
}
return: int;
}
call_method_protected @const {
params {
@in x: int;
}
return: int;
}
@property protected_prop @protected {
get {}
set {}
values {
data: int;
}
}
@property public_getter_private_setter {
get {}
set @protected {}
values {
data: int;
}
}
@property static_prop @static {
get {}
set {}
values {
data: int;
}
}
}
events {
nonconflicted: void;

View File

@ -1,4 +1,6 @@
#define DUMMY_TEST_IFACE_PROTECTED
#include "libefl_mono_native_test.h"
typedef struct Dummy_Test_Object_Data
@ -4704,6 +4706,16 @@ const Eina_Value_Type *_dummy_test_object_mirror_value_type(EINA_UNUSED const Eo
return type;
}
int _dummy_test_object_dummy_test_iface_method_protected(EINA_UNUSED const Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, int x)
{
return -x;
}
int _dummy_test_object_dummy_test_iface_call_method_protected(const Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, int x)
{
return dummy_test_iface_method_protected(obj, x);
}
// Inherit
int _dummy_inherit_helper_receive_dummy_and_call_int_out(Dummy_Test_Object *x)
{

View File

@ -1653,6 +1653,8 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
Efl.Object.provider_find;
Dummy.Test_Iface.emit_nonconflicted;
Dummy.Test_Iface.iface_prop { get; set; }
Dummy.Test_Iface.method_protected;
Dummy.Test_Iface.call_method_protected;
}
events {
evt,with,string @hot: const(string);

View File

@ -46,7 +46,6 @@ static void
_unregister(Eo *eo, void* data EINA_UNUSED, Efl_Ui_Focus_Object *child)
{
unregistered = eina_list_append(unregistered, child);
printf("UNREGISTERED %p %s\n", child, efl_name_get(child));
efl_ui_focus_manager_calc_unregister(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child);
}