diff --git a/src/Libs/GObject-2.0/Public/Object2.cs b/src/Libs/GObject-2.0/Public/Object2.cs
new file mode 100644
index 000000000..76a6c3507
--- /dev/null
+++ b/src/Libs/GObject-2.0/Public/Object2.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using GLib;
+using GObject.Internal;
+
+namespace GObject
+{
+ public class Object2 : IDisposable
+ {
+ private readonly Object2Handle _handle;
+
+ public Object2(Object2Handle handle)
+ {
+ _handle = handle;
+ _handle.AddMemoryPressure();
+ }
+
+ public IntPtr GetHandle() => _handle.DangerousGetHandle();
+
+ public void Dispose()
+ {
+ _handle.Dispose();
+ }
+ }
+}
+
+
+namespace GObject.Internal
+{
+ public class ToggleRef2 : IDisposable
+ {
+ private readonly IntPtr _handle;
+ private readonly ToggleNotify _callback;
+
+ private object _reference;
+
+ public object? Object
+ {
+ get
+ {
+ if(_reference is WeakReference weakRef)
+ return weakRef.Target;
+
+ return _reference;
+ }
+ }
+
+ ///
+ /// Initializes a toggle ref. The given object must be already owned by C# as the owned
+ /// reference is exchanged with a toggling reference meaning the toggle reference is taking control
+ /// over the reference.
+ /// This object saves a strong reference to the given object which prevents it from beeing garbage
+ /// collected. This strong reference is hold as long as there are other than our own toggling ref
+ /// on the given object.
+ /// If our toggeling ref is the last ref on the given object the strong reference is changed into a
+ /// weak reference. This allows the garbage collector to free the C# object which must result in the
+ /// call of the Dispose method of the ToggleRef. The Dispose method removes the added toggle reference
+ /// and thus frees the last reference to the C object.
+ ///
+ public ToggleRef2(Object2 obj)
+ {
+ _reference = obj;
+ _handle = obj.GetHandle();
+
+ _callback = ToggleReference;
+
+ RegisterToggleRef();
+ }
+
+ private void RegisterToggleRef()
+ {
+ Internal.Object.AddToggleRef(_handle, _callback, IntPtr.Zero);
+ Internal.Object.Unref(_handle);
+ }
+
+ private void ToggleReference(IntPtr data, IntPtr @object, bool isLastRef)
+ {
+ if (!isLastRef && _reference is WeakReference weakRef)
+ {
+ if (weakRef.Target is { } weakObj)
+ _reference = weakObj;
+ else
+ throw new Exception($"Handle {_handle}: Could not toggle reference to strong. It got garbage collected.");
+ }
+ else if (isLastRef && _reference is not WeakReference)
+ {
+ _reference = new WeakReference(_reference);
+ }
+ }
+
+ public void Dispose()
+ {
+ var sourceFunc = new GLib.Internal.SourceFuncAsyncHandler(() =>
+ {
+ Internal.Object.RemoveToggleRef(_handle, _callback, IntPtr.Zero);
+ return false;
+ });
+ GLib.Internal.MainContext.Invoke(GLib.Internal.MainContextUnownedHandle.NullHandle, sourceFunc.NativeCallback, IntPtr.Zero);
+ }
+ }
+
+ public class ObjectMapper2
+ {
+ private static readonly Dictionary WrapperObjects = new();
+
+ public static bool TryGetObject(IntPtr handle, [NotNullWhen(true)] out T? obj) where T : Object2
+ {
+ if (WrapperObjects.TryGetValue(handle, out ToggleRef2? toggleRef))
+ {
+ if (toggleRef.Object is not null)
+ {
+ obj = (T) toggleRef.Object;
+ return true;
+ }
+ }
+
+ obj = null;
+ return false;
+ }
+ }
+
+ public class ObjectWrapper2
+ {
+ public static T? WrapNullableHandle(IntPtr handle, bool ownedRef) where T : Object2
+ {
+ return handle == IntPtr.Zero
+ ? null
+ : WrapHandle(handle, ownedRef);
+ }
+
+ public static T WrapHandle(IntPtr handle, bool ownedRef) where T : Object2
+ {
+ if (handle == IntPtr.Zero)
+ throw new NullReferenceException($"Failed to wrap handle as type <{typeof(T).FullName}>. Null handle passed to WrapHandle.");
+
+ if (ObjectMapper2.TryGetObject(handle, out T? obj))
+ return obj;
+ }
+ }
+
+ public class Object2Handle : SafeHandle
+ {
+ public override bool IsInvalid => handle == IntPtr.Zero;
+
+ public Object2Handle(IntPtr handle, bool ownsHandle) : base(IntPtr.Zero, true)
+ {
+ SetHandle(handle);
+ OwnReference(ownsHandle);
+ }
+
+ private void OwnReference(bool ownedRef)
+ {
+ if (!ownedRef)
+ {
+ // - Unowned GObjects need to be refed to bind them to this instance
+ // - Unowned InitiallyUnowned floating objects need to be ref_sinked
+ // - Unowned InitiallyUnowned non-floating objects need to be refed
+ // As ref_sink behaves like ref in case of non floating instances we use it for all 3 cases
+ Object.RefSink(handle);
+ }
+ else
+ {
+ //In case we own the ref because the ownership was fully transfered to us we
+ //do not need to ref the object at all.
+
+ Debug.Assert(!Internal.Object.IsFloating(handle), $"Handle {handle}: Owned floating references are not possible.");
+ }
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ RemoveMemoryPressure();
+ Object.Unref(handle);
+ return true;
+ }
+
+ protected internal virtual void AddMemoryPressure() { }
+ protected virtual void RemoveMemoryPressure() { }
+ }
+}
+
+
+
diff --git a/src/Libs/GdkPixbuf-2.0/Public/Pixbuf2.cs b/src/Libs/GdkPixbuf-2.0/Public/Pixbuf2.cs
new file mode 100644
index 000000000..934d69c7e
--- /dev/null
+++ b/src/Libs/GdkPixbuf-2.0/Public/Pixbuf2.cs
@@ -0,0 +1,55 @@
+using System;
+using GdkPixbuf.Internal;
+using GObject.Internal;
+
+namespace GdkPixbuf
+{
+ public class Pixbuf2 : GObject.Object2
+ {
+ public Pixbuf2(Pixbuf2Handle handle) : base(handle) { }
+
+ public static Pixbuf2 New(Colorspace colorspace, bool hasAlpha, int bitsPerSample, int width, int height)
+ {
+ //TODO: How is the instance kept alive in case C# does not need it anymore, but C does?
+ var handle = Internal.Pixbuf.New(colorspace, hasAlpha, bitsPerSample, width, height);
+ return new Pixbuf2(new Pixbuf2Handle(handle, true));
+ }
+
+
+ [Version("2.12")]
+ public Pixbuf2? ApplyEmbeddedOrientation()
+ {
+ var resultApplyEmbeddedOrientation = GdkPixbuf.Internal.Pixbuf.ApplyEmbeddedOrientation(GetHandle());
+
+
+
+ return ObjectWrapper2.WrapNullableHandle(resultApplyEmbeddedOrientation, true);
+ }
+ }
+}
+
+namespace GdkPixbuf.Internal
+{
+ public class Pixbuf2Handle : GObject.Internal.Object2Handle
+ {
+ private long _size;
+
+ public Pixbuf2Handle(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle)
+ {
+ }
+
+ protected override void AddMemoryPressure()
+ {
+ _size = (long) Internal.Pixbuf.GetByteLength(handle);
+ GC.AddMemoryPressure(_size);
+ }
+
+ protected override void RemoveMemoryPressure()
+ {
+ GC.RemoveMemoryPressure(_size);
+ }
+ }
+}
+
+
+