mirror of
https://gitee.com/csharpui/CPF.git
synced 2025-07-15 14:04:34 +08:00
102 lines
2.8 KiB
C#
102 lines
2.8 KiB
C#
![]() |
using System;
|
||
|
using System.Runtime.InteropServices;
|
||
|
|
||
|
namespace CPF.Mac.CoreFoundation
|
||
|
{
|
||
|
public abstract class CFRunLoopSourceCustom : CFRunLoopSource
|
||
|
{
|
||
|
private delegate void ScheduleCallback(IntPtr info, IntPtr runLoop, IntPtr mode);
|
||
|
|
||
|
private delegate void CancelCallback(IntPtr info, IntPtr runLoop, IntPtr mode);
|
||
|
|
||
|
private delegate void PerformCallback(IntPtr info);
|
||
|
|
||
|
private GCHandle gch;
|
||
|
|
||
|
[DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
|
||
|
private static extern IntPtr CFRunLoopSourceCreate(IntPtr allocator, int order, IntPtr context);
|
||
|
|
||
|
protected CFRunLoopSourceCustom()
|
||
|
: base(IntPtr.Zero, ownsHandle: true)
|
||
|
{
|
||
|
gch = GCHandle.Alloc(this);
|
||
|
CFRunLoopSourceContext structure = new CFRunLoopSourceContext
|
||
|
{
|
||
|
Info = GCHandle.ToIntPtr(gch),
|
||
|
Schedule = Marshal.GetFunctionPointerForDelegate<ScheduleCallback>(Schedule),
|
||
|
Cancel = Marshal.GetFunctionPointerForDelegate<CancelCallback>(Cancel),
|
||
|
Perform = Marshal.GetFunctionPointerForDelegate<PerformCallback>(Perform)
|
||
|
};
|
||
|
IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CFRunLoopSourceContext)));
|
||
|
try
|
||
|
{
|
||
|
Marshal.StructureToPtr(structure, intPtr, fDeleteOld: false);
|
||
|
handle = CFRunLoopSourceCreate(IntPtr.Zero, 0, intPtr);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Marshal.FreeHGlobal(intPtr);
|
||
|
}
|
||
|
if (handle == IntPtr.Zero)
|
||
|
{
|
||
|
throw new NotSupportedException();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[MonoPInvokeCallback(typeof(ScheduleCallback))]
|
||
|
private static void Schedule(IntPtr info, IntPtr runLoop, IntPtr mode)
|
||
|
{
|
||
|
CFRunLoopSourceCustom cFRunLoopSourceCustom = GCHandle.FromIntPtr(info).Target as CFRunLoopSourceCustom;
|
||
|
CFRunLoop cFRunLoop = new CFRunLoop(runLoop);
|
||
|
CFString cFString = new CFString(mode);
|
||
|
try
|
||
|
{
|
||
|
cFRunLoopSourceCustom.OnSchedule(cFRunLoop, cFString);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
cFRunLoop.Dispose();
|
||
|
cFString.Dispose();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected abstract void OnSchedule(CFRunLoop loop, string mode);
|
||
|
|
||
|
[MonoPInvokeCallback(typeof(CancelCallback))]
|
||
|
private static void Cancel(IntPtr info, IntPtr runLoop, IntPtr mode)
|
||
|
{
|
||
|
CFRunLoopSourceCustom cFRunLoopSourceCustom = GCHandle.FromIntPtr(info).Target as CFRunLoopSourceCustom;
|
||
|
CFRunLoop cFRunLoop = new CFRunLoop(runLoop);
|
||
|
CFString cFString = new CFString(mode);
|
||
|
try
|
||
|
{
|
||
|
cFRunLoopSourceCustom.OnCancel(cFRunLoop, cFString);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
cFRunLoop.Dispose();
|
||
|
cFString.Dispose();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected abstract void OnCancel(CFRunLoop loop, string mode);
|
||
|
|
||
|
[MonoPInvokeCallback(typeof(PerformCallback))]
|
||
|
private static void Perform(IntPtr info)
|
||
|
{
|
||
|
(GCHandle.FromIntPtr(info).Target as CFRunLoopSourceCustom).OnPerform();
|
||
|
}
|
||
|
|
||
|
protected abstract void OnPerform();
|
||
|
|
||
|
public override void Dispose(bool disposing)
|
||
|
{
|
||
|
if (disposing && gch.IsAllocated)
|
||
|
{
|
||
|
gch.Free();
|
||
|
}
|
||
|
base.Dispose(disposing);
|
||
|
}
|
||
|
}
|
||
|
}
|