Files
osu-framework/osu.Framework.iOS/IOSWindow.cs
2024-05-21 19:29:08 +09:00

85 lines
2.7 KiB
C#

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ObjCRuntime;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Platform;
using osu.Framework.Platform.SDL3;
using SDL;
using UIKit;
namespace osu.Framework.iOS
{
internal class IOSWindow : SDL3MobileWindow
{
private UIWindow? window;
public override Size Size
{
get => base.Size;
protected set
{
base.Size = value;
if (window != null)
updateSafeArea();
}
}
public IOSWindow(GraphicsSurfaceType surfaceType, string appName)
: base(surfaceType, appName)
{
}
public override void Create()
{
base.Create();
window = Runtime.GetNSObject<UIWindow>(WindowHandle);
updateSafeArea();
}
protected override unsafe void RunMainLoop()
{
// Delegate running the main loop to CADisplayLink.
//
// Note that this is most effective in single thread mode.
// .. In multi-threaded mode it will time the *input* thread to the callbacks. This is kinda silly,
// but users shouldn't be using multi-threaded mode in the first place. Disabling it completely on
// iOS may be a good forward direction if this ever comes up, as a user may see a potentially higher
// frame rate with multi-threaded mode turned on, but it is going to give them worse input latency
// and higher power usage.
SDL3.SDL_iOSSetEventPump(SDL_bool.SDL_FALSE);
SDL3.SDL_iOSSetAnimationCallback(SDLWindowHandle, 1, &runFrame, ObjectHandle.Handle);
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static void runFrame(IntPtr userdata)
{
var handle = new ObjectHandle<IOSWindow>(userdata);
if (handle.GetTarget(out IOSWindow window))
window.RunFrame();
}
private void updateSafeArea()
{
Debug.Assert(window != null);
SafeAreaPadding.Value = new MarginPadding
{
Top = (float)window.SafeAreaInsets.Top * Scale,
Left = (float)window.SafeAreaInsets.Left * Scale,
Bottom = (float)window.SafeAreaInsets.Bottom * Scale,
Right = (float)window.SafeAreaInsets.Right * Scale,
};
}
}
}