// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace Microsoft.Maui.Platform.Linux.Native; /// /// Safe handle wrapper for GTK widget pointers. /// Releases the widget via gtk_widget_destroy when disposed. /// internal class SafeGtkWidgetHandle : SafeHandleZeroOrMinusOneIsInvalid { [DllImport("libgtk-3.so.0")] private static extern void gtk_widget_destroy(IntPtr widget); /// /// Initializes a new that owns the handle. /// public SafeGtkWidgetHandle() : base(ownsHandle: true) { } /// /// Initializes a new wrapping an existing pointer. /// /// The existing GTK widget pointer. /// Whether this safe handle is responsible for releasing the resource. public SafeGtkWidgetHandle(IntPtr existingHandle, bool ownsHandle = true) : base(ownsHandle) { SetHandle(existingHandle); } /// protected override bool ReleaseHandle() { gtk_widget_destroy(handle); return true; } } /// /// Safe handle wrapper for GObject pointers. /// Releases the object via g_object_unref when disposed. /// Suitable for any GObject-derived type including GtkCssProvider, GdkPixbuf, etc. /// internal class SafeGObjectHandle : SafeHandleZeroOrMinusOneIsInvalid { [DllImport("libgobject-2.0.so.0")] private static extern void g_object_unref(IntPtr obj); /// /// Initializes a new that owns the handle. /// public SafeGObjectHandle() : base(ownsHandle: true) { } /// /// Initializes a new wrapping an existing pointer. /// /// The existing GObject pointer. /// Whether this safe handle is responsible for releasing the resource. public SafeGObjectHandle(IntPtr existingHandle, bool ownsHandle = true) : base(ownsHandle) { SetHandle(existingHandle); } /// protected override bool ReleaseHandle() { g_object_unref(handle); return true; } } /// /// Safe handle wrapper for X11 Display* pointers. /// Releases the display connection via XCloseDisplay when disposed. /// internal class SafeX11DisplayHandle : SafeHandleZeroOrMinusOneIsInvalid { [DllImport("libX11.so.6")] private static extern int XCloseDisplay(IntPtr display); /// /// Initializes a new that owns the handle. /// public SafeX11DisplayHandle() : base(ownsHandle: true) { } /// /// Initializes a new wrapping an existing pointer. /// /// The existing X11 Display pointer. /// Whether this safe handle is responsible for releasing the resource. public SafeX11DisplayHandle(IntPtr existingHandle, bool ownsHandle = true) : base(ownsHandle) { SetHandle(existingHandle); } /// protected override bool ReleaseHandle() { XCloseDisplay(handle); return true; } } /// /// Safe handle wrapper for X11 Cursor resources. /// Releases the cursor via XFreeCursor when disposed. /// Requires the associated Display* to be provided at construction time, /// as X11 cursor cleanup requires both the display and cursor handles. /// internal class SafeX11CursorHandle : SafeHandleZeroOrMinusOneIsInvalid { [DllImport("libX11.so.6")] private static extern int XFreeCursor(IntPtr display, IntPtr cursor); private readonly IntPtr _display; /// /// Initializes a new that owns the handle. /// /// /// The X11 Display pointer required for releasing the cursor. /// The caller must ensure the display remains valid for the lifetime of this handle. /// public SafeX11CursorHandle(IntPtr display) : base(ownsHandle: true) { _display = display; } /// /// Initializes a new wrapping an existing cursor. /// /// /// The X11 Display pointer required for releasing the cursor. /// The caller must ensure the display remains valid for the lifetime of this handle. /// /// The existing X11 Cursor handle. /// Whether this safe handle is responsible for releasing the resource. public SafeX11CursorHandle(IntPtr display, IntPtr existingHandle, bool ownsHandle = true) : base(ownsHandle) { _display = display; SetHandle(existingHandle); } /// protected override bool ReleaseHandle() { if (_display != IntPtr.Zero) { XFreeCursor(_display, handle); } return true; } } /// /// Safe handle wrapper for GtkCssProvider* pointers. /// Since GtkCssProvider is a GObject, this releases it via g_object_unref when disposed. /// internal class SafeCssProviderHandle : SafeHandleZeroOrMinusOneIsInvalid { [DllImport("libgobject-2.0.so.0")] private static extern void g_object_unref(IntPtr obj); /// /// Initializes a new that owns the handle. /// public SafeCssProviderHandle() : base(ownsHandle: true) { } /// /// Initializes a new wrapping an existing pointer. /// /// The existing GtkCssProvider pointer. /// Whether this safe handle is responsible for releasing the resource. public SafeCssProviderHandle(IntPtr existingHandle, bool ownsHandle = true) : base(ownsHandle) { SetHandle(existingHandle); } /// protected override bool ReleaseHandle() { g_object_unref(handle); return true; } }