Fix properties setting when constructing GLib.Objects
This is a proper fix of old FIXME. It defers setting of managed properties during GLib.Object construction until we have paired Managed and Unmanaged objects.
This commit is contained in:
parent
b20872aa41
commit
5a7a0f7a3c
1 changed files with 40 additions and 17 deletions
|
@ -36,6 +36,7 @@ namespace GLib {
|
||||||
bool disposed = false;
|
bool disposed = false;
|
||||||
static uint idx = 1;
|
static uint idx = 1;
|
||||||
static Dictionary<IntPtr, ToggleRef> Objects = new Dictionary<IntPtr, ToggleRef>();
|
static Dictionary<IntPtr, ToggleRef> Objects = new Dictionary<IntPtr, ToggleRef>();
|
||||||
|
static Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>> PropertiesToSet = new Dictionary<IntPtr, Dictionary<IntPtr, GLib.Value>>();
|
||||||
|
|
||||||
~Object ()
|
~Object ()
|
||||||
{
|
{
|
||||||
|
@ -89,7 +90,9 @@ namespace GLib {
|
||||||
|
|
||||||
ToggleRef toggle_ref;
|
ToggleRef toggle_ref;
|
||||||
lock (Objects) {
|
lock (Objects) {
|
||||||
toggle_ref = (ToggleRef) Objects[o];
|
if (!Objects.TryGetValue (o, out toggle_ref)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toggle_ref != null) {
|
if (toggle_ref != null) {
|
||||||
|
@ -406,7 +409,9 @@ namespace GLib {
|
||||||
GType gtype = new GLib.GType (gtypeval);
|
GType gtype = new GLib.GType (gtypeval);
|
||||||
GObjectClass threshold_class = (GObjectClass) Marshal.PtrToStructure (gtype.GetThresholdType ().GetClassPtr (), typeof (GObjectClass));
|
GObjectClass threshold_class = (GObjectClass) Marshal.PtrToStructure (gtype.GetThresholdType ().GetClassPtr (), typeof (GObjectClass));
|
||||||
IntPtr raw = threshold_class.constructor_cb (gtypeval, n_construct_properties, construct_properties);
|
IntPtr raw = threshold_class.constructor_cb (gtypeval, n_construct_properties, construct_properties);
|
||||||
bool construct_needed = true;
|
Dictionary<IntPtr, GLib.Value> deferred;
|
||||||
|
|
||||||
|
GLib.Object obj = null;
|
||||||
for (int i = 0; i < n_construct_properties; i++) {
|
for (int i = 0; i < n_construct_properties; i++) {
|
||||||
IntPtr p = new IntPtr (construct_properties.ToInt64 () + i * 2 * IntPtr.Size);
|
IntPtr p = new IntPtr (construct_properties.ToInt64 () + i * 2 * IntPtr.Size);
|
||||||
|
|
||||||
|
@ -417,16 +422,21 @@ namespace GLib {
|
||||||
Value val = (Value) Marshal.PtrToStructure (Marshal.ReadIntPtr (p, IntPtr.Size), typeof (Value));
|
Value val = (Value) Marshal.PtrToStructure (Marshal.ReadIntPtr (p, IntPtr.Size), typeof (Value));
|
||||||
if ((IntPtr) val.Val != IntPtr.Zero) {
|
if ((IntPtr) val.Val != IntPtr.Zero) {
|
||||||
GCHandle gch = (GCHandle) (IntPtr) val.Val;
|
GCHandle gch = (GCHandle) (IntPtr) val.Val;
|
||||||
Object o = (GLib.Object) gch.Target;
|
obj = (GLib.Object) gch.Target;
|
||||||
o.Raw = raw;
|
obj.Raw = raw;
|
||||||
construct_needed = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (construct_needed)
|
if (obj == null)
|
||||||
GetObject (raw, false);
|
obj = GetObject (raw, false);
|
||||||
|
|
||||||
|
if(PropertiesToSet.TryGetValue(raw, out deferred)) {
|
||||||
|
foreach(var item in deferred) {
|
||||||
|
SetDeferredProperty(obj, item.Value, item.Key);
|
||||||
|
}
|
||||||
|
PropertiesToSet.Remove(raw);
|
||||||
|
}
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,17 +521,30 @@ namespace GLib {
|
||||||
|
|
||||||
static void SetPropertyCallback(IntPtr handle, uint property_id, ref GLib.Value value, IntPtr param_spec)
|
static void SetPropertyCallback(IntPtr handle, uint property_id, ref GLib.Value value, IntPtr param_spec)
|
||||||
{
|
{
|
||||||
// FIXME: Here is a big quick hack to avoid race condition when trying to set up adjustment with contructor
|
// There are multiple issues in this place.
|
||||||
// Because Raw is set too late
|
// We cannot construct an object here as it can be in construction
|
||||||
if (param_spec != IntPtr.Zero) {
|
// from ConstructorCallback thus managed object already created.
|
||||||
ParamSpec foo = new ParamSpec(param_spec);
|
//
|
||||||
if (foo.Name == "gtk-sharp-managed-instance") {
|
// We cannot use the "gtk-sharp-managed-instance" property as when
|
||||||
GCHandle gch = (GCHandle) (IntPtr) value.Val;
|
// constructed by Gtk.Builder it is set to null.
|
||||||
Object o = (GLib.Object) gch.Target;
|
//
|
||||||
o.Raw = handle;
|
// We defer setting the properties to later time when
|
||||||
|
// we have unmanaged and managed objects paired.
|
||||||
|
GLib.Object obj = TryGetObject(handle);
|
||||||
|
if(obj != null) {
|
||||||
|
SetDeferredProperty(obj, value, param_spec);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
Dictionary<IntPtr, GLib.Value> deferred;
|
||||||
|
if(!PropertiesToSet.TryGetValue(handle, out deferred)) {
|
||||||
|
deferred = new Dictionary<IntPtr, GLib.Value>();
|
||||||
|
PropertiesToSet.Add(handle, deferred);
|
||||||
}
|
}
|
||||||
GLib.Object obj = GLib.Object.GetObject (handle, false);
|
deferred[param_spec] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetDeferredProperty(GLib.Object obj, GLib.Value value, IntPtr param_spec)
|
||||||
|
{
|
||||||
var type = (Type)obj.LookupGType ();
|
var type = (Type)obj.LookupGType ();
|
||||||
|
|
||||||
Dictionary<IntPtr, PropertyInfo> props;
|
Dictionary<IntPtr, PropertyInfo> props;
|
||||||
|
|
Loading…
Add table
Reference in a new issue