Browse Source

Add API to prevent App Nap.

pull/8894/head
Stan Wijckmans 3 years ago
parent
commit
2273534a57
  1. 4
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  2. 39
      native/Avalonia.Native/src/OSX/PlatformBehaviorInhibition.mm
  3. 1
      native/Avalonia.Native/src/OSX/common.h
  4. 11
      native/Avalonia.Native/src/OSX/main.mm
  5. 12
      src/Avalonia.Base/Platform/IPlatformBehaviorInhibition.cs
  6. 13
      src/Avalonia.Controls/PlatformInhibitionType.cs
  7. 25
      src/Avalonia.Controls/TopLevel.cs
  8. 21
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  9. 20
      src/Avalonia.Native/PlatformBehaviorInhibition.cs
  10. 7
      src/Avalonia.Native/avn.idl

4
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@ -43,6 +43,7 @@
523484CA26EA688F00EA0C2C /* trayicon.mm in Sources */ = {isa = PBXBuildFile; fileRef = 523484C926EA688F00EA0C2C /* trayicon.mm */; };
5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; };
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; };
855EDC9F28C6546F00807998 /* PlatformBehaviorInhibition.mm in Sources */ = {isa = PBXBuildFile; fileRef = 855EDC9E28C6546F00807998 /* PlatformBehaviorInhibition.mm */; };
AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; };
AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1E522B217613570091CD71 /* OpenGL.framework */; };
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; };
@ -95,6 +96,7 @@
5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = "<group>"; };
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = "<group>"; };
5BF943652167AD1D009CAE35 /* cursor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = "<group>"; };
855EDC9E28C6546F00807998 /* PlatformBehaviorInhibition.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformBehaviorInhibition.mm; sourceTree = "<group>"; };
AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
AB1E522B217613570091CD71 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@ -140,6 +142,7 @@
AB7A61E62147C814003C5833 = {
isa = PBXGroup;
children = (
855EDC9E28C6546F00807998 /* PlatformBehaviorInhibition.mm */,
BC11A5BC2608D58F0017BAD0 /* automation.h */,
BC11A5BD2608D58F0017BAD0 /* automation.mm */,
1A1852DB23E05814008F0DED /* deadlock.mm */,
@ -288,6 +291,7 @@
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */,
BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */,
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
855EDC9F28C6546F00807998 /* PlatformBehaviorInhibition.mm in Sources */,
520624B322973F4100C4DCEF /* menu.mm in Sources */,
37A517B32159597E00FBA241 /* Screens.mm in Sources */,
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */,

39
native/Avalonia.Native/src/OSX/PlatformBehaviorInhibition.mm

@ -0,0 +1,39 @@
#include "common.h"
namespace
{
id<NSObject> s_inhibitAppSleepHandle{};
}
class PlatformBehaviorInhibition : public ComSingleObject<IAvnPlatformBehaviorInhibition, &IID_IAvnCursorFactory>
{
public:
FORWARD_IUNKNOWN()
virtual void SetInhibitAppSleep(bool inhibitAppSleep, char* reason) override
{
START_COM_CALL;
@autoreleasepool
{
if (inhibitAppSleep && s_inhibitAppSleepHandle == nullptr)
{
NSActivityOptions options = NSActivityUserInitiatedAllowingIdleSystemSleep;
s_inhibitAppSleepHandle = [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:[NSString stringWithUTF8String: reason]];
}
if (!inhibitAppSleep)
{
s_inhibitAppSleepHandle = nullptr;
}
}
}
};
extern IAvnPlatformBehaviorInhibition* CreatePlatformBehaviorInhibition()
{
@autoreleasepool
{
return new PlatformBehaviorInhibition();
}
}

1
native/Avalonia.Native/src/OSX/common.h

@ -26,6 +26,7 @@ extern IAvnTrayIcon* CreateTrayIcon();
extern IAvnMenuItem* CreateAppMenuItem();
extern IAvnMenuItem* CreateAppMenuItemSeparator();
extern IAvnApplicationCommands* CreateApplicationCommands();
extern IAvnPlatformBehaviorInhibition* CreatePlatformBehaviorInhibition();
extern IAvnNativeControlHost* CreateNativeControlHost(NSView* parent);
extern IAvnPlatformSettings* CreatePlatformSettings();
extern void SetAppMenu(IAvnMenu *menu);

11
native/Avalonia.Native/src/OSX/main.mm

@ -408,6 +408,17 @@ public:
return S_OK;
}
}
virtual HRESULT CreatePlatformBehaviorInhibition(IAvnPlatformBehaviorInhibition** ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreatePlatformBehaviorInhibition();
return S_OK;
}
}
};
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()

12
src/Avalonia.Base/Platform/IPlatformBehaviorInhibition.cs

@ -0,0 +1,12 @@
using System.Threading.Tasks;
namespace Avalonia.Platform
{
/// <summary>
/// Allows to inhibit platform specific behavior.
/// </summary>
public interface IPlatformBehaviorInhibition
{
Task SetInhibitAppSleep(bool inhibitAppSleep, string reason);
}
}

13
src/Avalonia.Controls/PlatformInhibitionType.cs

@ -0,0 +1,13 @@
namespace Avalonia.Controls
{
/// <summary>
/// A platform specific behavior that can be inhibited.
/// </summary>
public enum PlatformInhibitionType
{
/// <summary>
/// When inhibited, prevents the app from being put to sleep or being given a lower priority when not in focus.
/// </summary>
AppSleep
}
}

25
src/Avalonia.Controls/TopLevel.cs

@ -20,6 +20,7 @@ using Avalonia.Styling;
using Avalonia.Utilities;
using Avalonia.Input.Platform;
using System.Linq;
using System.Threading.Tasks;
namespace Avalonia.Controls
{
@ -570,6 +571,30 @@ namespace Avalonia.Controls
/// <param name="e">The event args.</param>
protected virtual void OnClosed(EventArgs e) => Closed?.Invoke(this, e);
/// <summary>
/// Requests a <see cref="PlatformInhibitionType"/> to be inhibited.
/// The behavior remains inhibited until the return value is disposed.
/// The available set of <see cref="PlatformInhibitionType"/>s depends on the platform.
/// If a behavior is inhibited on a platform where this type is not supported the request will have no effect.
/// </summary>
protected async Task<IDisposable> RequestPlatformInhibition(PlatformInhibitionType type, string reason)
{
var platformBehaviorInhibition = PlatformImpl?.TryGetFeature<IPlatformBehaviorInhibition>();
if (platformBehaviorInhibition == null)
{
return Disposable.Create(() => { });
}
switch (type)
{
case PlatformInhibitionType.AppSleep:
await platformBehaviorInhibition.SetInhibitAppSleep(true, reason);
return Disposable.Create(() => platformBehaviorInhibition.SetInhibitAppSleep(false, reason).Wait());
default:
return Disposable.Create(() => { });
}
}
/// <summary>
/// Tries to get a service from an <see cref="IAvaloniaDependencyResolver"/>, logging a
/// warning if not found.

21
src/Avalonia.Native/AvaloniaNativePlatform.cs

@ -158,25 +158,4 @@ namespace Avalonia.Native
throw new NotImplementedException();
}
}
public class AvaloniaNativeMacOptions
{
private readonly IAvnMacOptions _opts;
private bool _showInDock;
internal AvaloniaNativeMacOptions(IAvnMacOptions opts)
{
_opts = opts;
ShowInDock = true;
}
public bool ShowInDock
{
get => _showInDock;
set
{
_showInDock = value;
_opts.SetShowInDock(value ? 1 : 0);
}
}
}
}

20
src/Avalonia.Native/PlatformBehaviorInhibition.cs

@ -0,0 +1,20 @@
using System.Threading.Tasks;
using Avalonia.Native.Interop;
using Avalonia.Platform;
namespace Avalonia.Native
{
internal class PlatformBehaviorInhibition : IPlatformBehaviorInhibition
{
readonly IAvnPlatformBehaviorInhibition _native;
internal PlatformBehaviorInhibition(IAvnPlatformBehaviorInhibition native)
=> _native = native;
public Task SetInhibitAppSleep(bool inhibitAppSleep, string reason)
{
_native.SetInhibitAppSleep(inhibitAppSleep ? 1 : 0, reason);
return Task.CompletedTask;
}
}
}

7
src/Avalonia.Native/avn.idl

@ -503,6 +503,7 @@ interface IAvaloniaNativeFactory : IUnknown
HRESULT CreateTrayIcon(IAvnTrayIcon** ppv);
HRESULT CreateApplicationCommands(IAvnApplicationCommands** ppv);
HRESULT CreatePlatformSettings(IAvnPlatformSettings** ppv);
HRESULT CreatePlatformBehaviorInhibition(IAvnPlatformBehaviorInhibition** ppv);
}
[uuid(233e094f-9b9f-44a3-9a6e-6948bbdd9fb1)]
@ -924,3 +925,9 @@ interface IAvnPlatformSettings : IUnknown
uint GetAccentColor();
void RegisterColorsChange(IAvnActionCallback* callback);
}
[uuid(12edf00d-5803-4d3f-9947-b4840e5e9372)]
interface IAvnPlatformBehaviorInhibition : IUnknown
{
void SetInhibitAppSleep(bool inhibitAppSleep, char* reason);
}

Loading…
Cancel
Save