Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/KappaDuck.Quack/Interop/SDL/Primitives/SDL_Locale.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

namespace KappaDuck.Quack.Interop.SDL.Primitives;

[StructLayout(LayoutKind.Sequential)]
internal readonly struct SDL_Locale
{
public byte* Language { get; }

public byte* Country { get; }
}
9 changes: 9 additions & 0 deletions src/KappaDuck.Quack/Interop/SDL/SDL3.System.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

using KappaDuck.Quack.Interop.SDL.Primitives;
using KappaDuck.Quack.System;

namespace KappaDuck.Quack.Interop.SDL;
Expand All @@ -21,6 +22,14 @@ internal static partial class SDL3
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
internal static partial PowerState GetPowerInfo(out int seconds, out int percent);

[LibraryImport(nameof(SDL3), EntryPoint = "SDL_GetPreferredLocales")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
internal static partial SDL_Locale** GetPreferredLocales(out int count);

[LibraryImport(nameof(SDL3), EntryPoint = "SDL_GetSystemRAM")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
internal static partial int GetSystemRAM();

[LibraryImport(nameof(SDL3), EntryPoint = "SDL_GetSystemTheme")]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
internal static partial Theme GetSystemTheme();
Expand Down
115 changes: 115 additions & 0 deletions src/KappaDuck.Quack/System/DeviceInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

using KappaDuck.Quack.Interop.SDL.Marshalling;
using KappaDuck.Quack.Interop.SDL.Primitives;
using System.Globalization;

namespace KappaDuck.Quack.System;

/// <summary>
/// Represents the device on which is currently running.
/// </summary>
public static class DeviceInfo
{
/// <summary>
/// Gets the operating system's process architecture, e.g. <see cref="Architecture.X64"/> or <see cref="Architecture.X86"/>.
/// </summary>
public static Architecture Architecture { get; } = RuntimeInformation.OSArchitecture;

/// <summary>
/// Gets the user's preferred cultures.
/// </summary>
/// <remarks>
/// This might be a "slow" call that has to query the operating system. It's best to ask for this once and save
/// the results. However, this list can change, usually because the user has changed a system preference outside
/// of your application; Quack! will send an event so you can update by calling this method again.
/// </remarks>
public static IReadOnlyList<CultureInfo> Cultures
{
get
{
SDL_Locale** locales = SDL3.GetPreferredLocales(out int count);

if (locales is null || count == 0)
return [];

List<CultureInfo> cultures = [with(count)];

unsafe
{
for (int i = 0; i < count; i++)
{
SDL_Locale* locale = locales[i];

string language = SDLStringMarshaller.ConvertToManaged(locale->Language)!;
string? country = SDLStringMarshaller.ConvertToManaged(locale->Country);

if (TryGetCulture(language, country, out CultureInfo? culture))
cultures.Add(culture);
}
}

SDL3.Free(locales);

return cultures;
}
}

/// <summary>
/// Gets the platform name
/// </summary>
public static string Platform { get; } = RuntimeInformation.OSDescription;

/// <summary>
/// Gets a snapshot of the current power supply.
/// </summary>
/// <remarks>
/// <para>
/// You should never take the power status for granted. Batteries (especially failing ones) can
/// report incorrect values, and the values reported here are best estimates based on what the
/// hardware reports. It's not uncommon for older batteries to lose stored power much faster than
/// reported, or completely drain when reporting it has 20% left, etc.
/// </para>
/// <para>
/// Battery status can change at any time, so if your application depends on accurate power status,
/// refresh the values by reading this property again, and perhaps ignore changes until they seem
/// stable for a few seconds. A platform may only report battery percentage or time left, not both.
/// </para>
/// <para>
/// On some platforms retrieving power details can be expensive; for continuous display, read it
/// about once a minute rather than every frame.
/// </para>
/// </remarks>
public static PowerInfo Power => PowerInfo.Capture();

/// <summary>
/// Gets the number of processors available to the current process.
/// </summary>
public static int ProcessorCount => Environment.ProcessorCount;

/// <summary>
/// Gets the amount of RAM configured in the system in MiB.
/// </summary>
public static long RAM { get; } = SDL3.GetSystemRAM();

/// <summary>
/// Gets the current system theme.
/// </summary>
public static Theme Theme => SDL3.GetSystemTheme();

private static bool TryGetCulture(string language, string? country, [NotNullWhen(true)] out CultureInfo? culture)
{
string name = string.IsNullOrEmpty(country) ? language : $"{language}-{country}";
try
{
culture = CultureInfo.GetCultureInfo(name);
return true;
}
catch (CultureNotFoundException)
{
culture = null;
return false;
}
}
}
42 changes: 9 additions & 33 deletions src/KappaDuck.Quack/System/PowerInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,6 @@ private PowerInfo(PowerState state, int? percentage, TimeSpan? remaining)
Remaining = remaining;
}

/// <summary>
/// Gets a snapshot of the current power supply.
/// </summary>
/// <remarks>
/// <para>
/// You should never take the power status for granted. Batteries (especially failing ones) can
/// report incorrect values, and the values reported here are best estimates based on what the
/// hardware reports. It's not uncommon for older batteries to lose stored power much faster than
/// reported, or completely drain when reporting it has 20% left, etc.
/// </para>
/// <para>
/// Battery status can change at any time, so if your application depends on accurate power status,
/// refresh the values by reading this property again, and perhaps ignore changes until they seem
/// stable for a few seconds. A platform may only report battery percentage or time left, not both.
/// </para>
/// <para>
/// On some platforms retrieving power details can be expensive; for continuous display, read it
/// about once a minute rather than every frame.
/// </para>
/// </remarks>
public static PowerInfo Current
{
get
{
PowerState state = SDL3.GetPowerInfo(out int seconds, out int percent);

int? percentage = percent < 0 ? null : percent;
TimeSpan? remaining = seconds < 0 ? null : TimeSpan.FromSeconds(seconds);

return new PowerInfo(state, percentage, remaining);
}
}

/// <summary>
/// Gets the power state of the system.
/// </summary>
Expand Down Expand Up @@ -83,4 +50,13 @@ public static PowerInfo Current
/// </summary>
public bool HasBattery => State is PowerState.OnBattery or PowerState.Charging or PowerState.Charged;

internal static PowerInfo Capture()
{
PowerState state = SDL3.GetPowerInfo(out int seconds, out int percent);

int? percentage = percent < 0 ? null : percent;
TimeSpan? remaining = seconds < 0 ? null : TimeSpan.FromSeconds(seconds);

return new PowerInfo(state, percentage, remaining);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
namespace KappaDuck.Quack.System;

/// <summary>
/// Provides access to system preferences.
/// Controls whether the system screen saver may activate while the application runs.
/// </summary>
public static class SystemPreferences
public static class ScreenSaver
{
/// <summary>
/// Gets or sets a value indicating whether the screen saver is enabled.
Expand All @@ -18,15 +18,14 @@ public static class SystemPreferences
/// <para>The screen saver is disabled by default.</para>
/// </remarks>
/// <exception cref="QuackInteropException">Thrown if enabling or disabling the screen saver fails.</exception>
public static bool ScreenSaverEnabled
public static bool Enabled
{
get;
set
{
if (value)
{
SDLThrowHelper.ThrowIfFailed(SDL3.EnableScreenSaver());

field = true;
return;
}
Expand All @@ -35,9 +34,4 @@ public static bool ScreenSaverEnabled
field = false;
}
}

/// <summary>
/// Gets the current system theme.
/// </summary>
public static Theme Theme => SDL3.GetSystemTheme();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

namespace KappaDuck.Quack.Interop.Handles;
namespace KappaDuck.Quack.Windows.Handles;

/// <summary>
/// Represents a Wayland handle.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

namespace KappaDuck.Quack.Interop.Handles;
namespace KappaDuck.Quack.Windows.Handles;

/// <summary>
/// Represents a Win32 handle
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

namespace KappaDuck.Quack.Interop.Handles;
namespace KappaDuck.Quack.Windows.Handles;

/// <summary>
/// Represents the specific platform window handle.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) KappaDuck.
// Licensed under the MIT license.

namespace KappaDuck.Quack.Interop.Handles;
namespace KappaDuck.Quack.Windows.Handles;

/// <summary>
/// Represents a X11 handle.
Expand Down