diff --git a/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaController.cs b/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaController.cs
index e128ac7..23090fd 100644
--- a/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaController.cs
+++ b/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaController.cs
@@ -28,8 +28,48 @@ public static partial class MaaController
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
public static partial MaaControllerHandle MaaCustomControllerCreate([MarshalUsing(typeof(MaaMarshaller))] Custom.IMaaCustomController controller, nint controllerArg);
+ ///
+ /// Create a debug controller that serves images from a directory.
+ ///
+ /// Path to a directory of images (or a single image file).
+ /// The controller handle, or nint.Zero on failure.
+ [LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
+ public static partial MaaControllerHandle MaaDbgControllerCreate(string readPath);
+
+ ///
+ /// Create a macOS controller for native macOS applications.
+ ///
+ /// The CGWindowID of the target window (0 for desktop).
+ /// macOS screencap method to use.
+ /// macOS input method to use.
+ /// The controller handle, or nint.Zero on failure.
+ [LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
+ public static partial MaaControllerHandle MaaMacOSControllerCreate(uint windowId, MaaMacOSScreencapMethod screencapMethod, MaaMacOSInputMethod inputMethod);
+
+ ///
+ /// Create an Android native controller.
+ ///
+ /// JSON config for the control unit.
+ /// The controller handle, or nint.Zero on failure.
+ [LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
+ public static partial MaaControllerHandle MaaAndroidNativeControllerCreate(string configJson);
+
+ ///
+ /// Create a replay controller that replays recorded operations.
+ ///
+ /// Path to the recording JSONL file.
+ /// The controller handle, or nint.Zero on failure.
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
- public static partial MaaControllerHandle MaaDbgControllerCreate(string readPath, string writePath, MaaDbgControllerType type, string config);
+ public static partial MaaControllerHandle MaaReplayControllerCreate(string recordingPath);
+
+ ///
+ /// Create a record controller that wraps an existing controller and records all operations.
+ ///
+ /// The inner controller to forward all operations to.
+ /// Path to the recording JSONL file to write.
+ /// The record controller handle, or nint.Zero on failure.
+ [LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
+ public static partial MaaControllerHandle MaaRecordControllerCreate(MaaControllerHandle inner, string recordingPath);
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
public static partial void MaaControllerDestroy(MaaControllerHandle ctrl);
@@ -87,6 +127,9 @@ public static partial class MaaController
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
public static partial MaaCtrlId MaaControllerPostTouchUp(MaaControllerHandle ctrl, int contact);
+ [LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
+ public static partial MaaCtrlId MaaControllerPostRelativeMove(MaaControllerHandle ctrl, int dx, int dy);
+
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
public static partial MaaCtrlId MaaControllerPostKeyDown(MaaControllerHandle ctrl, int keycode);
diff --git a/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaTasker.cs b/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaTasker.cs
index 0046b3e..90ae9b2 100644
--- a/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaTasker.cs
+++ b/src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaTasker.cs
@@ -109,6 +109,10 @@ public static partial class MaaTasker
[return: MarshalAs(UnmanagedType.U1)]
public static partial bool MaaTaskerGetNodeDetail(MaaTaskerHandle tasker, MaaNodeId nodeId, MaaStringBufferHandle nodeName, out MaaRecoId recoId, out MaaActId actionId, [MarshalAs(UnmanagedType.U1)] out bool completed);
+ [LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static partial bool MaaTaskerGetWaitFreezesDetail(MaaTaskerHandle tasker, MaaWfId wfId, MaaStringBufferHandle nodeName, MaaStringBufferHandle phase, [MarshalAs(UnmanagedType.U1)] out bool success, out MaaSize elapsedMs, MaaRecoId[]? recoIdList, ref MaaSize recoIdListSize, MaaRectHandle roi);
+
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.U1)]
public static partial bool MaaTaskerGetTaskDetail(MaaTaskerHandle tasker, MaaTaskId taskId, MaaStringBufferHandle entry, MaaNodeId[] nodeIdList, ref MaaSize nodeIdListSize, out MaaStatus status);
diff --git a/src/MaaFramework.Binding.Native/Interop/Framework/MaaDef.cs b/src/MaaFramework.Binding.Native/Interop/Framework/MaaDef.cs
index 34a5784..0d8fadf 100644
--- a/src/MaaFramework.Binding.Native/Interop/Framework/MaaDef.cs
+++ b/src/MaaFramework.Binding.Native/Interop/Framework/MaaDef.cs
@@ -50,10 +50,15 @@
// No bitwise OR, just set it
global using MaaDbgControllerType = System.UInt64;
global using MaaControllerFeature = System.UInt64;
+// macOS controller types
+global using MaaMacOSScreencapMethod = System.UInt64;
+global using MaaMacOSInputMethod = System.UInt64;
// Gamepad types
global using MaaGamepadType = System.UInt64;
global using MaaGamepadButton = System.UInt64;
global using MaaGamepadTouch = System.UInt64;
+// WaitFreezes id
+global using MaaWfId = System.Int64;
global using MaaRectHandle = nint;
using System.Runtime.InteropServices;
diff --git a/src/MaaFramework.Binding.Native/Interop/Toolkit/MaaToolkitDef.cs b/src/MaaFramework.Binding.Native/Interop/Toolkit/MaaToolkitDef.cs
index bc13a1a..0261a5c 100644
--- a/src/MaaFramework.Binding.Native/Interop/Toolkit/MaaToolkitDef.cs
+++ b/src/MaaFramework.Binding.Native/Interop/Toolkit/MaaToolkitDef.cs
@@ -14,6 +14,7 @@
global using MaaToolkitAdbDeviceListHandle = nint;
global using MaaToolkitDesktopWindowHandle = nint;
global using MaaToolkitDesktopWindowListHandle = nint;
+global using MaaMacOSPermission = System.Int32;
namespace MaaFramework.Binding.Interop.Native;
diff --git a/src/MaaFramework.Binding.Native/Interop/Toolkit/MacOS/MaaToolkitMacOS.cs b/src/MaaFramework.Binding.Native/Interop/Toolkit/MacOS/MaaToolkitMacOS.cs
new file mode 100644
index 0000000..ffc34e1
--- /dev/null
+++ b/src/MaaFramework.Binding.Native/Interop/Toolkit/MacOS/MaaToolkitMacOS.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记
+#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
+
+using System.Runtime.InteropServices;
+
+namespace MaaFramework.Binding.Interop.Native;
+
+public static partial class MaaToolkitMacOS
+{
+ [LibraryImport("MaaToolkit")]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static partial bool MaaToolkitMacOSCheckPermission(MaaMacOSPermission perm);
+
+ [LibraryImport("MaaToolkit")]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static partial bool MaaToolkitMacOSRequestPermission(MaaMacOSPermission perm);
+
+ [LibraryImport("MaaToolkit")]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static partial bool MaaToolkitMacOSRevealPermissionSettings(MaaMacOSPermission perm);
+}
diff --git a/src/MaaFramework.Binding.Native/MaaController.cs b/src/MaaFramework.Binding.Native/MaaController.cs
index 47766e2..752e6ce 100644
--- a/src/MaaFramework.Binding.Native/MaaController.cs
+++ b/src/MaaFramework.Binding.Native/MaaController.cs
@@ -168,6 +168,13 @@ public MaaJob TouchMove(int contact, int x, int y, int pressure = 1)
public MaaJob TouchUp(int contact)
=> CreateJob(MaaControllerPostTouchUp(Handle, contact));
+ ///
+ ///
+ /// Wrapper of .
+ ///
+ public MaaJob RelativeMove(int dx, int dy)
+ => CreateJob(MaaControllerPostRelativeMove(Handle, dx, dy));
+
///
///
/// Wrapper of .
diff --git a/src/MaaFramework.Binding.Native/MaaController/MaaAndroidNativeController.cs b/src/MaaFramework.Binding.Native/MaaController/MaaAndroidNativeController.cs
new file mode 100644
index 0000000..728d087
--- /dev/null
+++ b/src/MaaFramework.Binding.Native/MaaController/MaaAndroidNativeController.cs
@@ -0,0 +1,46 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using static MaaFramework.Binding.Interop.Native.MaaController;
+
+namespace MaaFramework.Binding;
+
+///
+/// A wrapper class providing a reference implementation for .
+///
+[DebuggerDisplay("{DebuggerDisplay,nq}")]
+public class MaaAndroidNativeController : MaaController
+{
+ private readonly string _debugConfigJson;
+
+ [ExcludeFromCodeCoverage(Justification = "Debugger display.")]
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string DebuggerDisplay => IsInvalid
+ ? $"Invalid {GetType().Name}"
+ : $"{GetType().Name} {{ ConfigJson = {_debugConfigJson} }}";
+
+ ///
+ /// Creates a instance.
+ ///
+ /// JSON config for the control unit.
+ /// Executes if ; otherwise, not link.
+ /// Checks LinkStart().Wait() status if ; otherwise, not check.
+ ///
+ /// Wrapper of .
+ /// This controller is only available on Android.
+ ///
+ ///
+ ///
+ public MaaAndroidNativeController([StringSyntax("Json")] string configJson, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(configJson);
+
+ var handle = MaaAndroidNativeControllerCreate(configJson);
+ _ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
+ SetHandle(handle, needReleased: true);
+
+ _debugConfigJson = configJson;
+
+ if (link == LinkOption.Start)
+ LinkStartOnConstructed(check, configJson);
+ }
+}
diff --git a/src/MaaFramework.Binding.Native/MaaController/MaaDbgController.cs b/src/MaaFramework.Binding.Native/MaaController/MaaDbgController.cs
index 274910a..41e91a2 100644
--- a/src/MaaFramework.Binding.Native/MaaController/MaaDbgController.cs
+++ b/src/MaaFramework.Binding.Native/MaaController/MaaDbgController.cs
@@ -11,47 +11,37 @@ namespace MaaFramework.Binding;
public class MaaDbgController : MaaController
{
private readonly string _debugReadPath;
- private readonly string _debugWritePath;
- private readonly DbgControllerType _debugType;
- private readonly string _debugConfig;
[ExcludeFromCodeCoverage(Justification = "Debugger display.")]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay => IsInvalid
? $"Invalid {GetType().Name}"
- : $"{GetType().Name} {{ ReadFrom = {_debugReadPath}, WriteTo = {_debugWritePath}, Type = {_debugType}, Config = {_debugConfig} }}";
+ : $"{GetType().Name} {{ ReadFrom = {_debugReadPath} }}";
///
/// Creates a instance.
///
- /// The read path.
- /// The write path.
- /// The DebugControllerType.
- /// The config.
+ /// Path to a directory of images (or a single image file).
/// Executes if ; otherwise, not link.
/// Checks LinkStart().Wait() status if ; otherwise, not check.
///
/// Wrapper of .
+ /// Images are loaded on connect and cycled through on each screencap request.
+ /// All input operations (click, swipe, etc.) are no-ops that return success.
///
///
///
- public MaaDbgController(string readPath, string writePath, DbgControllerType type, [StringSyntax("Json")] string config = "{}", LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
+ public MaaDbgController(string readPath, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
{
ArgumentException.ThrowIfNullOrEmpty(readPath);
- ArgumentException.ThrowIfNullOrEmpty(writePath);
- if (type == DbgControllerType.None) throw new ArgumentException($"Value cannot be {DbgControllerType.None}.", nameof(type));
- ArgumentException.ThrowIfNullOrEmpty(config);
- var handle = MaaDbgControllerCreate(readPath, writePath, (MaaDbgControllerType)type, config);
+ var handle = MaaDbgControllerCreate(readPath);
_ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
SetHandle(handle, needReleased: true);
_debugReadPath = readPath;
- _debugWritePath = writePath;
- _debugType = type;
- _debugConfig = config;
if (link == LinkOption.Start)
- LinkStartOnConstructed(check, readPath, writePath, type, config);
+ LinkStartOnConstructed(check, readPath);
}
}
diff --git a/src/MaaFramework.Binding.Native/MaaController/MaaMacOSController.cs b/src/MaaFramework.Binding.Native/MaaController/MaaMacOSController.cs
new file mode 100644
index 0000000..0ecc125
--- /dev/null
+++ b/src/MaaFramework.Binding.Native/MaaController/MaaMacOSController.cs
@@ -0,0 +1,53 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using static MaaFramework.Binding.Interop.Native.MaaController;
+
+namespace MaaFramework.Binding;
+
+///
+/// A wrapper class providing a reference implementation for .
+///
+[DebuggerDisplay("{DebuggerDisplay,nq}")]
+public class MaaMacOSController : MaaController
+{
+ private readonly uint _debugWindowId;
+ private readonly MacOSScreencapMethod _debugScreencapMethod;
+ private readonly MacOSInputMethod _debugInputMethod;
+
+ [ExcludeFromCodeCoverage(Justification = "Debugger display.")]
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string DebuggerDisplay => IsInvalid
+ ? $"Invalid {GetType().Name}"
+ : $"{GetType().Name} {{ WindowId = {_debugWindowId}, ScreencapMethod = {_debugScreencapMethod}, InputMethod = {_debugInputMethod} }}";
+
+ ///
+ /// Creates a instance.
+ ///
+ /// The CGWindowID of the target window (0 for desktop).
+ /// macOS screencap method to use.
+ /// macOS input method to use.
+ /// Executes if ; otherwise, not link.
+ /// Checks LinkStart().Wait() status if ; otherwise, not check.
+ ///
+ /// Wrapper of .
+ /// This controller is designed for native macOS applications.
+ /// Requires Screen Recording permission for screencap.
+ /// Input simulation requires Accessibility permission.
+ /// Some features are not supported: start_app, stop_app, scroll.
+ /// Only single touch is supported (contact must be 0).
+ ///
+ ///
+ public MaaMacOSController(uint windowId, MacOSScreencapMethod screencapMethod, MacOSInputMethod inputMethod, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
+ {
+ var handle = MaaMacOSControllerCreate(windowId, (MaaMacOSScreencapMethod)screencapMethod, (MaaMacOSInputMethod)inputMethod);
+ _ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
+ SetHandle(handle, needReleased: true);
+
+ _debugWindowId = windowId;
+ _debugScreencapMethod = screencapMethod;
+ _debugInputMethod = inputMethod;
+
+ if (link == LinkOption.Start)
+ LinkStartOnConstructed(check, windowId, screencapMethod, inputMethod);
+ }
+}
diff --git a/src/MaaFramework.Binding.Native/MaaController/MaaRecordController.cs b/src/MaaFramework.Binding.Native/MaaController/MaaRecordController.cs
new file mode 100644
index 0000000..9e38ecd
--- /dev/null
+++ b/src/MaaFramework.Binding.Native/MaaController/MaaRecordController.cs
@@ -0,0 +1,51 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using static MaaFramework.Binding.Interop.Native.MaaController;
+
+namespace MaaFramework.Binding;
+
+///
+/// A wrapper class providing a reference implementation for .
+///
+[DebuggerDisplay("{DebuggerDisplay,nq}")]
+public class MaaRecordController : MaaController
+{
+ private readonly string _debugRecordingPath;
+
+ [ExcludeFromCodeCoverage(Justification = "Debugger display.")]
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string DebuggerDisplay => IsInvalid
+ ? $"Invalid {GetType().Name}"
+ : $"{GetType().Name} {{ RecordingPath = {_debugRecordingPath} }}";
+
+ ///
+ /// Creates a instance.
+ ///
+ /// The inner controller to forward all operations to. Must not be null.
+ /// Path to the recording JSONL file to write.
+ /// Executes if ; otherwise, not link.
+ /// Checks LinkStart().Wait() status if ; otherwise, not check.
+ ///
+ /// Wrapper of .
+ /// The record controller does NOT take ownership of the inner controller.
+ /// Screenshot images will be saved to a "{stem}-Screenshot" folder in the same directory as this file.
+ /// The recorded file can be replayed using .
+ ///
+ ///
+ ///
+ ///
+ public MaaRecordController(MaaController inner, string recordingPath, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
+ {
+ ArgumentNullException.ThrowIfNull(inner);
+ ArgumentException.ThrowIfNullOrEmpty(recordingPath);
+
+ var handle = MaaRecordControllerCreate(inner.Handle, recordingPath);
+ _ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
+ SetHandle(handle, needReleased: true);
+
+ _debugRecordingPath = recordingPath;
+
+ if (link == LinkOption.Start)
+ LinkStartOnConstructed(check, inner, recordingPath);
+ }
+}
diff --git a/src/MaaFramework.Binding.Native/MaaController/MaaReplayController.cs b/src/MaaFramework.Binding.Native/MaaController/MaaReplayController.cs
new file mode 100644
index 0000000..4755ed7
--- /dev/null
+++ b/src/MaaFramework.Binding.Native/MaaController/MaaReplayController.cs
@@ -0,0 +1,46 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using static MaaFramework.Binding.Interop.Native.MaaController;
+
+namespace MaaFramework.Binding;
+
+///
+/// A wrapper class providing a reference implementation for .
+///
+[DebuggerDisplay("{DebuggerDisplay,nq}")]
+public class MaaReplayController : MaaController
+{
+ private readonly string _debugRecordingPath;
+
+ [ExcludeFromCodeCoverage(Justification = "Debugger display.")]
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private string DebuggerDisplay => IsInvalid
+ ? $"Invalid {GetType().Name}"
+ : $"{GetType().Name} {{ RecordingPath = {_debugRecordingPath} }}";
+
+ ///
+ /// Creates a instance.
+ ///
+ /// Path to the recording JSONL file written by .
+ /// Executes if ; otherwise, not link.
+ /// Checks LinkStart().Wait() status if ; otherwise, not check.
+ ///
+ /// Wrapper of .
+ /// Screenshot image paths in the file are resolved relative to this file's parent directory.
+ ///
+ ///
+ ///
+ public MaaReplayController(string recordingPath, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
+ {
+ ArgumentException.ThrowIfNullOrEmpty(recordingPath);
+
+ var handle = MaaReplayControllerCreate(recordingPath);
+ _ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
+ SetHandle(handle, needReleased: true);
+
+ _debugRecordingPath = recordingPath;
+
+ if (link == LinkOption.Start)
+ LinkStartOnConstructed(check, recordingPath);
+ }
+}
diff --git a/src/MaaFramework.Binding.Native/MaaTasker.cs b/src/MaaFramework.Binding.Native/MaaTasker.cs
index b6e11e9..532851e 100644
--- a/src/MaaFramework.Binding.Native/MaaTasker.cs
+++ b/src/MaaFramework.Binding.Native/MaaTasker.cs
@@ -407,6 +407,36 @@ public bool GetActionDetail(MaaActId actionId, out string nodeName, out string a
return ret;
}
+ ///
+ public bool GetWaitFreezesDetail(MaaWfId wfId, out string nodeName, out string phase, out bool isSucceeded, out ulong elapsedMs, out MaaRecoId[] recoIdList, IMaaRectBuffer? roi)
+ => GetWaitFreezesDetail(wfId, out nodeName, out phase, out isSucceeded, out elapsedMs, out recoIdList, (MaaRectBuffer?)roi);
+
+ ///
+ ///
+ /// Wrapper of .
+ ///
+ public bool GetWaitFreezesDetail(MaaWfId wfId, out string nodeName, out string phase, out bool isSucceeded, out ulong elapsedMs, out MaaRecoId[] recoIdList, MaaRectBuffer? roi)
+ {
+ var roiHandle = roi?.Handle ?? MaaRectHandle.Zero;
+ MaaSize recoIdListSize = 0;
+
+ using var nodeNameBuffer = new MaaStringBuffer();
+ using var phaseBuffer = new MaaStringBuffer();
+
+ if (!MaaTaskerGetWaitFreezesDetail(Handle, wfId, nodeNameBuffer.Handle, phaseBuffer.Handle, out isSucceeded, out elapsedMs, null, ref recoIdListSize, roiHandle))
+ {
+ nodeName = string.Empty;
+ phase = string.Empty;
+ recoIdList = [];
+ return false;
+ }
+
+ nodeName = nodeNameBuffer.ToString();
+ phase = phaseBuffer.ToString();
+ recoIdList = recoIdListSize == 0 ? [] : new MaaRecoId[recoIdListSize];
+ return MaaTaskerGetWaitFreezesDetail(Handle, wfId, nodeNameBuffer.Handle, phaseBuffer.Handle, out isSucceeded, out elapsedMs, recoIdList, ref recoIdListSize, roiHandle);
+ }
+
///
///
/// Wrapper of .
diff --git a/src/MaaFramework.Binding.Native/MaaToolkit.cs b/src/MaaFramework.Binding.Native/MaaToolkit.cs
index 74c0c80..734c452 100644
--- a/src/MaaFramework.Binding.Native/MaaToolkit.cs
+++ b/src/MaaFramework.Binding.Native/MaaToolkit.cs
@@ -38,6 +38,9 @@ public MaaToolkit(bool init = false, string userPath = nameof(Environment.Curren
///
public IMaaToolkitDesktop Desktop { get; } = new DesktopClass();
+ ///
+ public IMaaToolkitMacOS MacOS { get; } = new MacOSClass();
+
///
protected internal class ConfigClass : IMaaToolkitConfig
{
@@ -101,4 +104,29 @@ public IMaaListBuffer Find()
return list;
}
}
+
+ ///
+ protected internal class MacOSClass : IMaaToolkitMacOS
+ {
+ ///
+ ///
+ /// Wrapper of .
+ ///
+ public bool CheckPermission(MacOSPermission permission)
+ => Interop.Native.MaaToolkitMacOS.MaaToolkitMacOSCheckPermission((MaaMacOSPermission)permission);
+
+ ///
+ ///
+ /// Wrapper of .
+ ///
+ public bool RequestPermission(MacOSPermission permission)
+ => Interop.Native.MaaToolkitMacOS.MaaToolkitMacOSRequestPermission((MaaMacOSPermission)permission);
+
+ ///
+ ///
+ /// Wrapper of .
+ ///
+ public bool RevealPermissionSettings(MacOSPermission permission)
+ => Interop.Native.MaaToolkitMacOS.MaaToolkitMacOSRevealPermissionSettings((MaaMacOSPermission)permission);
+ }
}
diff --git a/src/MaaFramework.Binding/Enums/Controllers/MacOSInputMethod.cs b/src/MaaFramework.Binding/Enums/Controllers/MacOSInputMethod.cs
new file mode 100644
index 0000000..6687e16
--- /dev/null
+++ b/src/MaaFramework.Binding/Enums/Controllers/MacOSInputMethod.cs
@@ -0,0 +1,24 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记
+#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
+
+namespace MaaFramework.Binding;
+
+///
+/// macOS input method.
+///
+[System.Flags]
+public enum MacOSInputMethod : System.UInt64
+{
+ None = 0,
+ GlobalEvent = 1,
+ PostToPid = (1 << 1),
+}
diff --git a/src/MaaFramework.Binding/Enums/Controllers/MacOSPermission.cs b/src/MaaFramework.Binding/Enums/Controllers/MacOSPermission.cs
new file mode 100644
index 0000000..6c6010c
--- /dev/null
+++ b/src/MaaFramework.Binding/Enums/Controllers/MacOSPermission.cs
@@ -0,0 +1,22 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记
+#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
+
+namespace MaaFramework.Binding;
+
+///
+/// macOS permission types.
+///
+public enum MacOSPermission : System.Int32
+{
+ ScreenCapture = 1,
+ Accessibility = 2,
+}
diff --git a/src/MaaFramework.Binding/Enums/Controllers/MacOSScreencapMethod.cs b/src/MaaFramework.Binding/Enums/Controllers/MacOSScreencapMethod.cs
new file mode 100644
index 0000000..9764168
--- /dev/null
+++ b/src/MaaFramework.Binding/Enums/Controllers/MacOSScreencapMethod.cs
@@ -0,0 +1,22 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记
+#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
+
+namespace MaaFramework.Binding;
+
+///
+/// macOS screencap method.
+///
+public enum MacOSScreencapMethod : System.UInt64
+{
+ None = 0,
+ ScreenCaptureKit = 1,
+}
diff --git a/src/MaaFramework.Binding/IMaaController.cs b/src/MaaFramework.Binding/IMaaController.cs
index 0f11c6b..57ca357 100644
--- a/src/MaaFramework.Binding/IMaaController.cs
+++ b/src/MaaFramework.Binding/IMaaController.cs
@@ -120,6 +120,14 @@ public interface IMaaController : IMaaCommon, IMaaOption, IMaa
///
MaaJob TouchUp(int contact);
+ ///
+ /// Moves the mouse/pointer relative to its current position.
+ ///
+ /// The relative horizontal offset.
+ /// The relative vertical offset.
+ /// A relative move .
+ MaaJob RelativeMove(int dx, int dy);
+
///
/// Usage: KeyDown -> KeyUp.
/// For adb controller, is from android key event.
diff --git a/src/MaaFramework.Binding/IMaaTasker.cs b/src/MaaFramework.Binding/IMaaTasker.cs
index 4b282b7..fd03497 100644
--- a/src/MaaFramework.Binding/IMaaTasker.cs
+++ b/src/MaaFramework.Binding/IMaaTasker.cs
@@ -154,6 +154,19 @@ bool GetRecognitionDetail(MaaRecoId recognitionId, out string nodeName, out s
/// if query was successful; otherwise, .
bool GetActionDetail(MaaActId actionId, out string nodeName, out string action, IMaaRectBuffer? box, out bool isSucceeded, out string detailJson);
+ ///
+ /// Gets the wait freezes detail.
+ ///
+ /// The wait freezes id.
+ /// The node name.
+ /// The phase (e.g. "pre", "post", "repeat", "context").
+ /// A value indicating whether the wait freezes is succeeded.
+ /// The elapsed time in milliseconds.
+ /// The recognition id list.
+ /// The region of interest.
+ /// if query was successful; otherwise, .
+ bool GetWaitFreezesDetail(MaaWfId wfId, out string nodeName, out string phase, out bool isSucceeded, out ulong elapsedMs, out MaaRecoId[] recoIdList, IMaaRectBuffer? roi);
+
///
/// Gets the node detail.
///
diff --git a/src/MaaFramework.Binding/IMaaToolkit.cs b/src/MaaFramework.Binding/IMaaToolkit.cs
index 4ba0ecd..6130b85 100644
--- a/src/MaaFramework.Binding/IMaaToolkit.cs
+++ b/src/MaaFramework.Binding/IMaaToolkit.cs
@@ -22,6 +22,11 @@ public interface IMaaToolkit
/// Gets the MaaToolkit Desktop.
///
IMaaToolkitDesktop Desktop { get; }
+
+ ///
+ /// Gets the MaaToolkit macOS helper.
+ ///
+ IMaaToolkitMacOS MacOS { get; }
}
///
@@ -89,3 +94,30 @@ public interface IMaaToolkitDesktopWindow
///
IMaaListBuffer Find();
}
+
+///
+/// An interface defining wrapped members for MaaToolkit macOS.
+///
+public interface IMaaToolkitMacOS
+{
+ ///
+ /// Checks if the specified macOS permission is granted.
+ ///
+ /// The permission to check.
+ /// if the permission is granted; otherwise, .
+ bool CheckPermission(MacOSPermission permission);
+
+ ///
+ /// Requests the specified macOS permission.
+ ///
+ /// The permission to request.
+ /// if the permission was granted; otherwise, .
+ bool RequestPermission(MacOSPermission permission);
+
+ ///
+ /// Reveals the system permission settings for the specified macOS permission.
+ ///
+ /// The permission to reveal settings for.
+ /// if the settings were revealed successfully; otherwise, .
+ bool RevealPermissionSettings(MacOSPermission permission);
+}
diff --git a/src/MaaFramework.Binding/MaaDef.cs b/src/MaaFramework.Binding/MaaDef.cs
index 3883e8b..f6e38b4 100644
--- a/src/MaaFramework.Binding/MaaDef.cs
+++ b/src/MaaFramework.Binding/MaaDef.cs
@@ -4,6 +4,7 @@
global using MaaNodeId = System.Int64;
global using MaaRecoId = System.Int64;
global using MaaActId = System.Int64;
+global using MaaWfId = System.Int64;
global using MaaSize = System.UInt64;
using System.Diagnostics.CodeAnalysis;
diff --git a/src/MaaFramework.Binding/MaaMsg.cs b/src/MaaFramework.Binding/MaaMsg.cs
index d1af735..824bbe1 100644
--- a/src/MaaFramework.Binding/MaaMsg.cs
+++ b/src/MaaFramework.Binding/MaaMsg.cs
@@ -346,5 +346,40 @@ public static class Action
public const string Failed = "Node.Action.Failed";
}
+ public static class WaitFreezes
+ {
+ ///
+ /// Message for wait freezes.
+ ///
+ ///
+ /// details_json: { task_id: number, wf_id: number, name: string, phase: string, roi: [number, number, number, number], param: { time: number, threshold: number, method: number, rate_limit: number, timeout: number }, reco_ids?: number[], elapsed?: number, focus: any, }
+ ///
+ public const string Starting = "Node.WaitFreezes.Starting";
+
+ ///
+ /// Message for wait freezes.
+ ///
+ ///
+ /// details_json: { task_id: number, wf_id: number, name: string, phase: string, roi: [number, number, number, number], param: { time: number, threshold: number, method: number, rate_limit: number, timeout: number }, reco_ids?: number[], elapsed?: number, focus: any, }
+ ///
+ public const string Prefix = "Node.WaitFreezes";
+
+ ///
+ /// Message for wait freezes.
+ ///
+ ///
+ /// details_json: { task_id: number, wf_id: number, name: string, phase: string, roi: [number, number, number, number], param: { time: number, threshold: number, method: number, rate_limit: number, timeout: number }, reco_ids?: number[], elapsed?: number, focus: any, }
+ ///
+ public const string Succeeded = "Node.WaitFreezes.Succeeded";
+
+ ///
+ /// Message for wait freezes.
+ ///
+ ///
+ /// details_json: { task_id: number, wf_id: number, name: string, phase: string, roi: [number, number, number, number], param: { time: number, threshold: number, method: number, rate_limit: number, timeout: number }, reco_ids?: number[], elapsed?: number, focus: any, }
+ ///
+ public const string Failed = "Node.WaitFreezes.Failed";
+
+ }
}
}