Skip to content

Commit

Permalink
[CoreGraphics] Make P/Invokes in CGEvent have blittable signatures. (#…
Browse files Browse the repository at this point in the history
…20211)

Contributes towards #15684.
  • Loading branch information
rolfbjarne committed Feb 29, 2024
1 parent 6ef7d9c commit 9293323
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 35 deletions.
81 changes: 55 additions & 26 deletions src/CoreGraphics/CGEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ public CGEvent (CGEventSource? source, CGEventType mouseType, CGPoint mouseCurso
}

[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
extern static IntPtr CGEventCreateKeyboardEvent (IntPtr source, ushort virtualKey, [MarshalAs (UnmanagedType.I1)] bool keyDown);
extern static IntPtr CGEventCreateKeyboardEvent (IntPtr source, ushort virtualKey, byte keyDown);

public CGEvent (CGEventSource? source, ushort virtualKey, bool keyDown)
: base (CGEventCreateKeyboardEvent (source.GetHandle (), virtualKey, keyDown), true)
: base (CGEventCreateKeyboardEvent (source.GetHandle (), virtualKey, keyDown.AsByte ()), true)
{
}

Expand Down Expand Up @@ -406,41 +406,42 @@ public ulong Timestamp {
}

[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
extern static void CGEventTapEnable (IntPtr machPort, [MarshalAs (UnmanagedType.I1)] bool enable);
extern static void CGEventTapEnable (IntPtr machPort, byte enable);

public static void TapEnable (CFMachPort machPort)
{
if (machPort is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (machPort));
CGEventTapEnable (machPort.Handle, true);
CGEventTapEnable (machPort.Handle, 1);
}

public static void TapDisable (CFMachPort machPort)
{
if (machPort is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (machPort));
CGEventTapEnable (machPort.Handle, false);
CGEventTapEnable (machPort.Handle, 0);
}

[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
[return: MarshalAs (UnmanagedType.I1)]
extern static bool CGEventTapIsEnabled (IntPtr machPort);
extern static byte CGEventTapIsEnabled (IntPtr machPort);

public static bool IsTapEnabled (CFMachPort machPort)
{
if (machPort is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (machPort));
return CGEventTapIsEnabled (machPort.Handle);
return CGEventTapIsEnabled (machPort.Handle) != 0;
}

[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
unsafe extern static void CGEventKeyboardGetUnicodeString (IntPtr handle, nuint maxLen, out nuint actualLen, char *buffer);
unsafe extern static void CGEventKeyboardGetUnicodeString (IntPtr handle, nuint maxLen, nuint* actualLen, ushort *buffer);

public unsafe string GetUnicodeString ()
{
char *buffer = stackalloc char [40];
CGEventKeyboardGetUnicodeString (Handle, 40, out var actual, buffer);
return new String (buffer, 0, (int) actual);
const int bufferLength = 40;
ushort *buffer = stackalloc ushort [bufferLength];
nuint actual = 0;
CGEventKeyboardGetUnicodeString (Handle, bufferLength, &actual, buffer);
return new String ((char *) buffer, 0, (int) actual);
}

#if NET
Expand Down Expand Up @@ -500,16 +501,16 @@ public static void PostToPSN (CGEvent evt, IntPtr processSerialNumber)
unsafe extern static int /* CGError = int32_t */ CGGetEventTapList (
uint /* uint32_t */ maxNumberOfTaps,
CGEventTapInformation *tapList,
out uint /* uint32_t* */ eventTapCount);
uint* /* uint32_t* */ eventTapCount);

public unsafe CGEventTapInformation []? GetEventTapList ()
{
uint count;
if (CGGetEventTapList (0, null, out count) != 0)
if (CGGetEventTapList (0, null, &count) != 0)
return null;
var result = new CGEventTapInformation [count];
fixed (CGEventTapInformation *p = result){
if (CGGetEventTapList (count, p, out count) != 0)
if (CGGetEventTapList (count, p, &count) != 0)
return null;
}
return result;
Expand All @@ -521,9 +522,16 @@ public static void PostToPSN (CGEvent evt, IntPtr processSerialNumber)
#else
[Mac (11,0)]
#endif
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary, EntryPoint="CGPreflightListenEventAccess")]
[return: MarshalAs (UnmanagedType.I1)]
public static extern bool PreflightListenEventAccess ();
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
static extern byte CGPreflightListenEventAccess ();

#if NET
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("maccatalyst15.0")]
#else
[Mac (11,0)]
#endif
public static bool PreflightListenEventAccess () => CGPreflightListenEventAccess () != 0;

#if NET
[SupportedOSPlatform ("macos11.0")]
Expand All @@ -532,28 +540,49 @@ public static void PostToPSN (CGEvent evt, IntPtr processSerialNumber)
[Mac (11,0)]
#endif
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary, EntryPoint="CGRequestListenEventAccess")]
[return: MarshalAs (UnmanagedType.I1)]
public static extern bool RequestListenEventAccess ();
static extern byte CGRequestListenEventAccess ();

#if NET
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("maccatalyst15.0")]
#else
[Mac (11,0)]
#endif
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary, EntryPoint="CGPreflightPostEventAccess")]
[return: MarshalAs (UnmanagedType.I1)]
public static extern bool PreflightPostEventAccess ();
public static bool RequestListenEventAccess () => CGRequestListenEventAccess () != 0;

#if NET
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("maccatalyst15.0")]
#else
[Mac (11,0)]
#endif
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
static extern byte CGPreflightPostEventAccess ();

#if NET
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("maccatalyst15.0")]
#else
[Mac (11,0)]
#endif
public static bool PreflightPostEventAccess () => CGPreflightPostEventAccess () != 0;

#if NET
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("maccatalyst15.0")]
#else
[Mac (11,0)]
#endif
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary)]
static extern byte CGRequestPostEventAccess ();

#if NET
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("maccatalyst15.0")]
#else
[Mac (11,0)]
#endif
[DllImport (Constants.ApplicationServicesCoreGraphicsLibrary, EntryPoint="CGRequestPostEventAccess")]
[return: MarshalAs (UnmanagedType.I1)]
public static extern bool RequestPostEventAccess ();
public static bool RequestPostEventAccess () => CGRequestPostEventAccess () != 0;

}

Expand Down
9 changes: 0 additions & 9 deletions tests/cecil-tests/BlittablePInvokes.KnownFailures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,6 @@ public partial class BlittablePInvokes {
"Security.SslStatus Security.SslContext::SSLWrite(System.IntPtr,System.Byte*,System.IntPtr,System.IntPtr&)",
"System.Boolean CoreGraphics.CGColor::CGColorEqualToColor(System.IntPtr,System.IntPtr)",
"System.Boolean CoreGraphics.CGDisplay::CGDisplayIsCaptured(System.UInt32)",
"System.Boolean CoreGraphics.CGEvent::CGEventTapIsEnabled(System.IntPtr)",
"System.Boolean CoreGraphics.CGEvent::PreflightListenEventAccess()",
"System.Boolean CoreGraphics.CGEvent::PreflightPostEventAccess()",
"System.Boolean CoreGraphics.CGEvent::RequestListenEventAccess()",
"System.Boolean CoreGraphics.CGEvent::RequestPostEventAccess()",
"System.Boolean CoreGraphics.CGEventSource::GetButtonState(CoreGraphics.CGEventSourceStateID,CoreGraphics.CGMouseButton)",
"System.Boolean CoreGraphics.CGEventSource::GetKeyState(CoreGraphics.CGEventSourceStateID,System.UInt16)",
"System.Boolean CoreGraphics.CGImage::CGImageGetShouldInterpolate(System.IntPtr)",
Expand Down Expand Up @@ -364,7 +359,6 @@ public partial class BlittablePInvokes {
"System.Int32 AudioUnit.AudioUnit::AudioUnitGetProperty(System.IntPtr,AudioUnit.AudioUnitPropertyIDType,AudioUnit.AudioUnitScopeType,System.UInt32,System.UInt32&,System.UInt32&)",
"System.Int32 AudioUnit.AudioUnit::AudioUnitSetProperty(System.IntPtr,AudioUnit.AudioUnitPropertyIDType,AudioUnit.AudioUnitScopeType,System.UInt32,AudioToolbox.AudioStreamBasicDescription&,System.UInt32)",
"System.Int32 AudioUnit.AUGraph::NewAUGraph(System.IntPtr&)",
"System.Int32 CoreGraphics.CGEvent::CGGetEventTapList(System.UInt32,CoreGraphics.CGEventTapInformation*,System.UInt32&)",
"System.Int32 CoreMedia.CMBufferQueue::CMBufferQueueCreate(System.IntPtr,System.IntPtr,CoreMedia.CMBufferQueue/CMBufferCallbacks,System.IntPtr&)",
"System.Int32 CoreMedia.CMBufferQueue::CMBufferQueueCreate(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr&)",
"System.Int32 CoreVideo.CVDisplayLink::CVDisplayLinkTranslateTime(System.IntPtr,CoreVideo.CVTimeStamp,CoreVideo.CVTimeStamp&)",
Expand All @@ -380,7 +374,6 @@ public partial class BlittablePInvokes {
"System.Int32 Security.SslContext::SSLCopyALPNProtocols(System.IntPtr,System.IntPtr&)",
"System.Int32 Security.SslContext::SSLSetSessionTicketsEnabled(System.IntPtr,System.Boolean)",
"System.Int32 SystemConfiguration.NetworkReachability::SCNetworkReachabilityGetFlags(System.IntPtr,SystemConfiguration.NetworkReachabilityFlags&)",
"System.IntPtr CoreGraphics.CGEvent::CGEventCreateKeyboardEvent(System.IntPtr,System.UInt16,System.Boolean)",
"System.IntPtr CoreGraphics.CGFunction::CGFunctionCreate(System.IntPtr,System.IntPtr,System.Runtime.InteropServices.NFloat*,System.IntPtr,System.Runtime.InteropServices.NFloat*,CoreGraphics.CGFunction/CGFunctionCallbacks&)",
"System.IntPtr CoreGraphics.CGImage::CGImageCreate(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,CoreGraphics.CGBitmapFlags,System.IntPtr,System.Runtime.InteropServices.NFloat*,System.Boolean,CoreGraphics.CGColorRenderingIntent)",
"System.IntPtr CoreGraphics.CGImage::CGImageCreateWithJPEGDataProvider(System.IntPtr,System.Runtime.InteropServices.NFloat*,System.Boolean,CoreGraphics.CGColorRenderingIntent)",
Expand Down Expand Up @@ -447,8 +440,6 @@ public partial class BlittablePInvokes {
"System.IntPtr SystemConfiguration.NetworkReachability::SCNetworkReachabilityCreateWithAddressPair(System.IntPtr,System.IntPtr,SystemConfiguration.NetworkReachability/sockaddr_in&)",
"System.IntPtr SystemConfiguration.NetworkReachability::SCNetworkReachabilityCreateWithAddressPair(System.IntPtr,SystemConfiguration.NetworkReachability/sockaddr_in&,System.IntPtr)",
"System.IntPtr SystemConfiguration.NetworkReachability::SCNetworkReachabilityCreateWithAddressPair(System.IntPtr,SystemConfiguration.NetworkReachability/sockaddr_in&,SystemConfiguration.NetworkReachability/sockaddr_in&)",
"System.Void CoreGraphics.CGEvent::CGEventKeyboardGetUnicodeString(System.IntPtr,System.UIntPtr,System.UIntPtr&,System.Char*)",
"System.Void CoreGraphics.CGEvent::CGEventTapEnable(System.IntPtr,System.Boolean)",
"System.Void CoreGraphics.CGPath::CGPathAddArc(System.IntPtr,CoreGraphics.CGAffineTransform*,System.Runtime.InteropServices.NFloat,System.Runtime.InteropServices.NFloat,System.Runtime.InteropServices.NFloat,System.Runtime.InteropServices.NFloat,System.Runtime.InteropServices.NFloat,System.Boolean)",
"System.Void CoreGraphics.CGPDFDocument::CGPDFDocumentGetVersion(System.IntPtr,System.Int32&,System.Int32&)",
"System.Void CoreGraphics.CGRectExtensions::CGRectDivide(CoreGraphics.CGRect,CoreGraphics.CGRect&,CoreGraphics.CGRect&,System.Runtime.InteropServices.NFloat,CoreGraphics.CGRectEdge)",
Expand Down

8 comments on commit 9293323

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.