Skip to content

Commit 1833efd

Browse files
CopilotMistEOmoomiji
authored
Add missing C API bindings for MaaFramework (#22)
* feat: support IMaaController ClickV2 & SwipeV2 MaaXYZ/MaaFramework#1056 * feat: Gamepad controller MaaXYZ/MaaFramework#1055 * feat: IMaaController.GetResolution() MaaXYZ/MaaFramework#1040 * feat: IMaaCustomController.Connected() MaaXYZ/MaaFramework#1030 --------- Co-authored-by: MistEO <18511905+MistEO@users.noreply.github.com> Co-authored-by: moomiji <35213527+moomiji@users.noreply.github.com>
1 parent 58442b7 commit 1833efd

13 files changed

Lines changed: 467 additions & 38 deletions

File tree

src/MaaFramework.Binding.Native/Extensions/DesktopWindowInfoExtensions.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,54 @@ public static MaaWin32Controller ToWin32Controller(this DesktopWindowInfo info,
5151

5252
return new MaaWin32Controller(info, link, check);
5353
}
54+
55+
/// <summary>
56+
/// Converts a <see cref="DesktopWindowInfo"/> to a <see cref="MaaGamepadController"/>.
57+
/// </summary>
58+
/// <param name="info">The DesktopWindowInfo.</param>
59+
/// <param name="gamepadType">The type of virtual gamepad.</param>
60+
/// <param name="screencapMethod">The screencap method.</param>
61+
/// <param name="hWnd">The new handle to a win32 window.</param>
62+
/// <param name="link">Executes <see cref="MaaController.LinkStart"/> if <see cref="LinkOption.Start"/>; otherwise, not link.</param>
63+
/// <param name="check">Checks LinkStart().Wait() status if <see cref="CheckStatusOption.ThrowIfNotSucceeded"/>; otherwise, not check.</param>
64+
/// <returns>A MaaGamepadController.</returns>
65+
/// <exception cref="ArgumentNullException"/>
66+
public static MaaGamepadController ToGamepadControllerWith(this DesktopWindowInfo info,
67+
GamepadType gamepadType,
68+
Win32ScreencapMethod? screencapMethod = null,
69+
nint? hWnd = null,
70+
LinkOption link = LinkOption.Start,
71+
CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
72+
{
73+
ArgumentNullException.ThrowIfNull(info);
74+
75+
if (hWnd == nint.Zero)
76+
return new MaaGamepadController(gamepadType, null, link, check);
77+
78+
var handle = hWnd ?? info.Handle;
79+
return new MaaGamepadController(
80+
gamepadType,
81+
new DesktopWindowInfo(
82+
handle,
83+
handle == info.Handle ? info.Name : string.Empty,
84+
handle == info.Handle ? info.ClassName : string.Empty,
85+
screencapMethod ?? info.ScreencapMethod,
86+
Win32InputMethod.None,
87+
Win32InputMethod.None
88+
),
89+
link,
90+
check
91+
);
92+
}
93+
94+
/// <inheritdoc cref="ToGamepadControllerWith(DesktopWindowInfo, GamepadType, Win32ScreencapMethod?, nint?, LinkOption, CheckStatusOption)"/>
95+
public static MaaGamepadController ToGamepadController(this DesktopWindowInfo info,
96+
GamepadType gamepadType,
97+
LinkOption link = LinkOption.Start,
98+
CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
99+
{
100+
ArgumentNullException.ThrowIfNull(info);
101+
102+
return new MaaGamepadController(gamepadType, info, link, check);
103+
}
54104
}

src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaController.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,19 @@ public static partial class MaaController
5353
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
5454
public static partial MaaCtrlId MaaControllerPostClick(MaaControllerHandle ctrl, int x, int y);
5555

56+
// for adb controller, contact means finger id (0 for first finger, 1 for second finger, etc)
57+
// for win32 controller, contact means mouse button id (0 for left, 1 for right, 2 for middle)
58+
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
59+
public static partial MaaCtrlId MaaControllerPostClickV2(MaaControllerHandle ctrl, int x, int y, int contact, int pressure);
60+
5661
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
5762
public static partial MaaCtrlId MaaControllerPostSwipe(MaaControllerHandle ctrl, int x1, int y1, int x2, int y2, int duration);
5863

64+
// for adb controller, contact means finger id (0 for first finger, 1 for second finger, etc)
65+
// for win32 controller, contact means mouse button id (0 for left, 1 for right, 2 for middle)
66+
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
67+
public static partial MaaCtrlId MaaControllerPostSwipeV2(MaaControllerHandle ctrl, int x1, int y1, int x2, int y2, int duration, int contact, int pressure);
68+
5969
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
6070
public static partial MaaCtrlId MaaControllerPostClickKey(MaaControllerHandle ctrl, int keycode);
6171

@@ -99,6 +109,19 @@ public static partial class MaaController
99109
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
100110
public static partial MaaControllerHandle MaaPlayCoverControllerCreate(string address, string uuid);
101111

112+
/// <summary>
113+
/// Create a virtual gamepad controller for Windows.
114+
/// </summary>
115+
/// <param name="hWnd">Window handle for screencap (optional, can be nint.Zero if screencap not needed).</param>
116+
/// <param name="gamepadType">Type of virtual gamepad (MaaGamepadType_Xbox360 or MaaGamepadType_DualShock4).</param>
117+
/// <param name="screencapMethod">Win32 screencap method to use. Ignored if hWnd is nint.Zero.</param>
118+
/// <returns>The controller handle, or nint.Zero on failure.</returns>
119+
/// <remarks>
120+
/// <para>Requires ViGEm Bus Driver to be installed on the system.</para>
121+
/// </remarks>
122+
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
123+
public static partial MaaControllerHandle MaaGamepadControllerCreate(nint hWnd, MaaGamepadType gamepadType, MaaWin32ScreencapMethod screencapMethod);
124+
102125
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
103126
public static partial MaaStatus MaaControllerStatus(MaaControllerHandle ctrl, MaaCtrlId id);
104127

@@ -117,6 +140,20 @@ public static partial class MaaController
117140
[return: MarshalAs(UnmanagedType.U1)]
118141
public static partial bool MaaControllerGetUuid(MaaControllerHandle ctrl, MaaStringBufferHandle buffer);
119142

143+
/// <summary>
144+
/// Get the raw (unscaled) device resolution.
145+
/// </summary>
146+
/// <param name="ctrl">The controller handle.</param>
147+
/// <param name="width">Output parameter for the raw width.</param>
148+
/// <param name="height">Output parameter for the raw height.</param>
149+
/// <returns>true if the resolution is available, false otherwise.</returns>
150+
/// <remarks>
151+
/// <para>This returns the actual device screen resolution before any scaling.</para>
152+
/// </remarks>
153+
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
154+
[return: MarshalAs(UnmanagedType.U1)]
155+
public static partial bool MaaControllerGetResolution(MaaControllerHandle ctrl, out int width, out int height);
156+
120157
[Obsolete]
121158
[LibraryImport("MaaFramework", StringMarshalling = StringMarshalling.Utf8)]
122159
public static partial MaaCtrlId MaaControllerPostPressKey(MaaControllerHandle ctrl, int keycode);

src/MaaFramework.Binding.Native/Interop/Framework/Instance/MaaCustomController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ private sealed class Delegates(IMaaCustomController managed)
9494
{
9595
public int Times = 0;
9696
public ConnectDelegate Connect = (nint transArg) => managed.Connect();
97+
public ConnectedDelegate Connected = (nint transArg) => managed.Connected();
9798
public RequestUuidDelegate RequestUuid = (nint transArg, MaaStringBufferHandle buffer) => managed.RequestUuid(new MaaStringBuffer(buffer));
9899
public GetFeaturesDelegate GetFeatures = (nint transArg) => (System.UInt64)managed.GetFeatures();
99100
public StartAppDelegate StartApp = (string intent, nint transArg) => managed.StartApp(intent);
@@ -122,6 +123,7 @@ private sealed class Delegates(IMaaCustomController managed)
122123
private sealed class Unmanaged(Delegates delegates)
123124
{
124125
public nint Connect = Marshal.GetFunctionPointerForDelegate(delegates.Connect);
126+
public nint Connected = Marshal.GetFunctionPointerForDelegate(delegates.Connected);
125127
public nint RequestUuid = Marshal.GetFunctionPointerForDelegate(delegates.RequestUuid);
126128
public nint GetFeatures = Marshal.GetFunctionPointerForDelegate(delegates.GetFeatures);
127129
public nint StartApp = Marshal.GetFunctionPointerForDelegate(delegates.StartApp);
@@ -143,6 +145,10 @@ private sealed class Unmanaged(Delegates delegates)
143145
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
144146
public delegate bool ConnectDelegate(nint transArg);
145147

148+
[return: MarshalAs(UnmanagedType.U1)]
149+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
150+
public delegate bool ConnectedDelegate(nint transArg);
151+
146152
/// <summary>
147153
/// Write result to buffer.
148154
/// </summary>

src/MaaFramework.Binding.Native/Interop/Framework/MaaDef.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
// No bitwise OR, just set it
5151
global using MaaDbgControllerType = System.UInt64;
5252
global using MaaControllerFeature = System.UInt64;
53+
// Gamepad types
54+
global using MaaGamepadType = System.UInt64;
55+
global using MaaGamepadButton = System.UInt64;
56+
global using MaaGamepadTouch = System.UInt64;
5357
global using MaaRectHandle = nint;
5458

5559
using System.Runtime.InteropServices;

src/MaaFramework.Binding.Native/MaaController.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,17 @@ public MaaJob LinkStart()
9999

100100
/// <inheritdoc/>
101101
/// <remarks>
102-
/// Wrapper of <see cref="MaaControllerPostClick"/>.
102+
/// Wrapper of <see cref="MaaControllerPostClickV2"/>.
103103
/// </remarks>
104-
public MaaJob Click(int x, int y)
105-
=> CreateJob(MaaControllerPostClick(Handle, x, y));
104+
public MaaJob Click(int x, int y, int contact = 0, int pressure = 1)
105+
=> CreateJob(MaaControllerPostClickV2(Handle, x, y, contact, pressure));
106106

107107
/// <inheritdoc/>
108108
/// <remarks>
109-
/// Wrapper of <see cref="MaaControllerPostSwipe"/>.
109+
/// Wrapper of <see cref="MaaControllerPostSwipeV2"/>.
110110
/// </remarks>
111-
public MaaJob Swipe(int x1, int y1, int x2, int y2, int duration)
112-
=> CreateJob(MaaControllerPostSwipe(Handle, x1, y1, x2, y2, duration));
111+
public MaaJob Swipe(int x1, int y1, int x2, int y2, int duration, int contact = 0, int pressure = 1)
112+
=> CreateJob(MaaControllerPostSwipeV2(Handle, x1, y1, x2, y2, duration, contact, pressure));
113113

114114
/// <inheritdoc/>
115115
/// <remarks>
@@ -151,14 +151,14 @@ public MaaJob StopApp(string intent)
151151
/// <remarks>
152152
/// Wrapper of <see cref="MaaControllerPostTouchDown"/>.
153153
/// </remarks>
154-
public MaaJob TouchDown(int contact, int x, int y, int pressure)
154+
public MaaJob TouchDown(int contact, int x, int y, int pressure = 1)
155155
=> CreateJob(MaaControllerPostTouchDown(Handle, contact, x, y, pressure));
156156

157157
/// <inheritdoc/>
158158
/// <remarks>
159159
/// Wrapper of <see cref="MaaControllerPostTouchMove"/>.
160160
/// </remarks>
161-
public MaaJob TouchMove(int contact, int x, int y, int pressure)
161+
public MaaJob TouchMove(int contact, int x, int y, int pressure = 1)
162162
=> CreateJob(MaaControllerPostTouchMove(Handle, contact, x, y, pressure));
163163

164164
/// <inheritdoc/>
@@ -280,4 +280,11 @@ public string? Uuid
280280
return uuid;
281281
}
282282
}
283+
284+
/// <inheritdoc/>
285+
/// <remarks>
286+
/// Wrapper of <see cref="MaaControllerGetResolution"/>.
287+
/// </remarks>
288+
public bool GetResolution(out int width, out int height)
289+
=> MaaControllerGetResolution(Handle, out width, out height);
283290
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Diagnostics;
3+
using static MaaFramework.Binding.Interop.Native.MaaController;
4+
5+
namespace MaaFramework.Binding;
6+
7+
/// <summary>
8+
/// A wrapper class providing a reference implementation for <see cref="MaaGamepadControllerCreate"/>.
9+
/// </summary>
10+
/// <remarks>
11+
/// <para>Requires ViGEm Bus Driver to be installed on the system.</para>
12+
/// <para>For gamepad control, use:</para>
13+
/// <para>- <c>ClickKey</c> / <c>KeyDown</c> / <c>KeyUp</c> :
14+
/// For digital buttons (A, B, X, Y, LB, RB, etc.)<br/>
15+
/// See <see cref="GamepadButton"/> for available buttons.</para>
16+
/// <para>- <c>TouchDown</c> / <c>TouchMove</c> / <c>TouchUp</c> :
17+
/// For analog inputs (sticks and triggers)<br/>
18+
/// See <see cref="GamepadTouch"/> for contact mapping.</para>
19+
/// <para>- <c>Click</c> / <c>Swipe</c> :
20+
/// Not directly supported for gamepad.</para>
21+
/// <para>- <c>InputText</c> / <c>StartApp</c> / <c>StopApp</c> / <c>Scroll</c> :
22+
/// Not supported.</para>
23+
/// </remarks>
24+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
25+
public class MaaGamepadController : MaaController
26+
{
27+
private readonly GamepadType _debugGamepadType;
28+
private readonly DesktopWindowInfo? _debugInfo;
29+
30+
[ExcludeFromCodeCoverage(Justification = "Debugger display.")]
31+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
32+
private string DebuggerDisplay => IsInvalid
33+
? $"Invalid {GetType().Name}"
34+
: $"{GetType().Name} {{ {DebuggerInfoString}, GamepadType = {_debugGamepadType} }}";
35+
36+
[ExcludeFromCodeCoverage(Justification = "Debugger display.")]
37+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
38+
private string DebuggerInfoString => _debugInfo is null
39+
? "No Screencap"
40+
: $"{nameof(_debugInfo.Name)} = {_debugInfo.Name}, {nameof(_debugInfo.ClassName)} = {_debugInfo.ClassName}, ScreencapMethod = {_debugInfo.ScreencapMethod}";
41+
42+
/// <summary>
43+
/// Creates a <see cref="MaaGamepadController"/> instance.
44+
/// </summary>
45+
/// <param name="gamepadType">The type of virtual gamepad.</param>
46+
/// <param name="info">The desktop window info (null if screencap not needed).</param>
47+
/// <param name="link">Executes <see cref="IMaaController.LinkStart"/> if <see cref="LinkOption.Start"/>; otherwise, not link.</param>
48+
/// <param name="check">Checks LinkStart().Wait() status if <see cref="CheckStatusOption.ThrowIfNotSucceeded"/>; otherwise, not check.</param>
49+
/// <remarks>
50+
/// Wrapper of <see cref="MaaGamepadControllerCreate"/>.
51+
/// </remarks>
52+
/// <exception cref="MaaJobStatusException"/>
53+
public MaaGamepadController(GamepadType gamepadType, DesktopWindowInfo? info = null, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
54+
{
55+
var handle = info is null
56+
? MaaGamepadControllerCreate(nint.Zero, (MaaGamepadType)gamepadType, 0UL)
57+
: MaaGamepadControllerCreate(info.Handle, (MaaGamepadType)gamepadType, (MaaWin32ScreencapMethod)info.ScreencapMethod);
58+
_ = MaaControllerAddSink(handle, MaaEventCallback, 5);
59+
SetHandle(handle, needReleased: true);
60+
61+
_debugGamepadType = gamepadType;
62+
_debugInfo = info;
63+
64+
if (link == LinkOption.Start)
65+
LinkStartOnConstructed(check, info, gamepadType);
66+
}
67+
68+
/// <param name="hWnd">Window handle for screencap (optional, can be <see cref="nint.Zero"/> if screencap not needed).</param>
69+
/// <param name="gamepadType">Type of virtual gamepad (<see cref="GamepadType.Xbox360"/> or <see cref="GamepadType.DualShock4"/>).</param>
70+
/// <param name="screencapMethod">Win32 screencap method to use. Ignored if hWnd is <see cref="nint.Zero"/>.</param>
71+
/// <param name="link">Executes <see cref="IMaaController.LinkStart"/> if <see cref="LinkOption.Start"/>; otherwise, not link.</param>
72+
/// <param name="check">Checks LinkStart().Wait() status if <see cref="CheckStatusOption.ThrowIfNotSucceeded"/>; otherwise, not check.</param>
73+
/// <inheritdoc cref="Binding.MaaGamepadController(GamepadType, DesktopWindowInfo, LinkOption, CheckStatusOption)"/>
74+
public MaaGamepadController(nint hWnd, GamepadType gamepadType, Win32ScreencapMethod screencapMethod, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
75+
: this(gamepadType, hWnd == nint.Zero ? null : new(hWnd, string.Empty, string.Empty, screencapMethod, Win32InputMethod.None, Win32InputMethod.None), link, check)
76+
{
77+
}
78+
79+
/// <summary>
80+
/// Clicks a key.
81+
/// </summary>
82+
/// <param name="key">The <see cref="GamepadButton"/> value.</param>
83+
/// <returns>A click key <see cref="MaaJob"/>.</returns>
84+
public MaaJob ClickKey(GamepadButton key)
85+
=> ClickKey(unchecked((int)key)); // GamepadButton < 0x1_0000_0000
86+
87+
/// <summary>
88+
/// Usage: KeyDown -> KeyUp.
89+
/// </summary>
90+
/// <param name="key">The <see cref="GamepadButton"/> value.</param>
91+
/// <returns>A key down <see cref="MaaJob"/>.</returns>
92+
public MaaJob KeyDown(GamepadButton key)
93+
=> KeyDown(unchecked((int)key)); // GamepadButton < 0x1_0000_0000
94+
95+
/// <returns>A key up <see cref="MaaJob"/>.</returns>
96+
/// <inheritdoc cref="KeyDown"/>
97+
public MaaJob KeyUp(GamepadButton key)
98+
=> KeyUp(unchecked((int)key)); // GamepadButton < 0x1_0000_0000
99+
100+
/// <summary>
101+
/// Usage: StickStart -> StickMove -> StickEnd.
102+
/// </summary>
103+
/// <param name="contact">The <see cref="GamepadTouch"/> value.</param>
104+
/// <param name="x">The horizontal coordinate of the point.</param>
105+
/// <param name="y">The vertical coordinate of the point.</param>
106+
/// <returns>A touch down <see cref="MaaJob"/>.</returns>
107+
public MaaJob StickStart(GamepadTouch contact, short x, short y)
108+
=> TouchDown(unchecked((int)contact), x, y, 0); // GamepadTouch < 0x1_0000_0000
109+
110+
/// <returns>A touch move <see cref="MaaJob"/>.</returns>
111+
/// <inheritdoc cref="StickStart"/>
112+
public MaaJob StickMove(GamepadTouch contact, short x, short y)
113+
=> TouchMove(unchecked((int)contact), x, y, 0); // GamepadTouch < 0x1_0000_0000
114+
115+
/// <returns>A touch up <see cref="MaaJob"/>.</returns>
116+
/// <inheritdoc cref="StickStart"/>
117+
public MaaJob StickEnd(GamepadTouch contact)
118+
=> TouchUp(unchecked((int)contact)); // GamepadTouch < 0x1_0000_0000
119+
120+
/// <summary>
121+
/// Usage: TriggerStart -> TriggerMove -> TriggerEnd.
122+
/// </summary>
123+
/// <param name="contact">The <see cref="GamepadTouch"/> value.</param>
124+
/// <param name="pressure">The pressure.</param>
125+
/// <returns>A touch down <see cref="MaaJob"/>.</returns>
126+
public MaaJob TriggerStart(GamepadTouch contact, byte pressure)
127+
=> TouchDown(unchecked((int)contact), 0, 0, pressure); // GamepadTouch < 0x1_0000_0000
128+
129+
/// <returns>A touch move <see cref="MaaJob"/>.</returns>
130+
/// <inheritdoc cref="StickStart"/>
131+
public MaaJob TriggerMove(GamepadTouch contact, byte pressure)
132+
=> TouchMove(unchecked((int)contact), 0, 0, pressure); // GamepadTouch < 0x1_0000_0000
133+
134+
/// <returns>A touch up <see cref="MaaJob"/>.</returns>
135+
/// <inheritdoc cref="StickStart"/>
136+
public MaaJob TriggerEnd(GamepadTouch contact)
137+
=> TouchUp(unchecked((int)contact)); // GamepadTouch < 0x1_0000_0000
138+
}

src/MaaFramework.Binding.UnitTests/Test_Custom.cs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -192,28 +192,15 @@ public bool Click(int x, int y)
192192
public bool Connect()
193193
=> c.LinkStart().Wait().IsSucceeded();
194194

195+
public bool Connected()
196+
=> c.IsConnected;
197+
195198
public bool InputText(string text)
196199
=> c.InputText(text).Wait().IsSucceeded();
197200

198201
public bool ClickKey(int keycode)
199202
=> c.ClickKey(keycode).Wait().IsSucceeded();
200203

201-
public bool RequestResolution(out int width, out int height)
202-
{
203-
#if MAA_NATIVE
204-
using var image = new MaaImageBuffer();
205-
#endif
206-
if (Screencap(image))
207-
{
208-
width = image.Width;
209-
height = image.Height;
210-
return true;
211-
}
212-
213-
width = height = -1;
214-
return false;
215-
}
216-
217204
public bool RequestUuid(in IMaaStringBuffer buffer)
218205
{
219206
var uuid = c.Uuid;

src/MaaFramework.Binding/Custom/IMaaCustomController.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,14 @@ namespace MaaFramework.Binding.Custom;
1010
public interface IMaaCustomController : IMaaCustomResource, IDisposable
1111
{
1212
bool Connect();
13+
bool Connected();
1314

1415
/// <remarks>
1516
/// Write result to buffer.
1617
/// </remarks>
1718
bool RequestUuid(in IMaaStringBuffer buffer);
1819
ControllerFeatures GetFeatures();
1920

20-
/// <remarks>
21-
/// Write result to width and height.
22-
/// </remarks>
23-
bool RequestResolution(out int width, out int height);
2421
bool StartApp(string intent);
2522
bool StopApp(string intent);
2623

0 commit comments

Comments
 (0)