Compare commits
37 Commits
Canary-1.2
...
44de9b378b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44de9b378b | ||
|
|
2ec032c48b | ||
|
|
f75efbea54 | ||
|
|
11f1922a82 | ||
|
|
de18c4927f | ||
|
|
78e7a3085a | ||
|
|
01e22f1c67 | ||
|
|
3352d70ea4 | ||
|
|
864cd57b51 | ||
|
|
06cd53925c | ||
|
|
33fefb1323 | ||
|
|
0c503e10ae | ||
|
|
1c6390cbfb | ||
|
|
c20452be61 | ||
|
|
b6667a8352 | ||
|
|
37b4dd2133 | ||
|
|
007d3bc045 | ||
|
|
be2aa5ae8f | ||
|
|
7f5978155b | ||
|
|
cd43362042 | ||
|
|
39e8283fb8 | ||
|
|
3e3de18976 | ||
|
|
a158a93d0a | ||
|
|
ff90b68d09 | ||
|
|
d7bd165861 | ||
|
|
5bfa01b58a | ||
|
|
7c30426f89 | ||
|
|
267aaca87d | ||
|
|
b9012e291b | ||
|
|
7da4a917ba | ||
|
|
4bab858793 | ||
|
|
ca7c17186e | ||
|
|
ea061cf60c | ||
|
|
d83da7d2fb | ||
|
|
25499cbbf6 | ||
|
|
8074a4dd87 | ||
|
|
13d2498405 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -129,11 +129,11 @@ jobs:
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Setup LLVM 17
|
||||
- name: Setup LLVM 14
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
sudo ./llvm.sh 14
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
|
||||
4
.github/workflows/canary.yml
vendored
4
.github/workflows/canary.yml
vendored
@@ -210,11 +210,11 @@ jobs:
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Setup LLVM 17
|
||||
- name: Setup LLVM 15
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
sudo ./llvm.sh 15
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -191,11 +191,11 @@ jobs:
|
||||
with:
|
||||
global-json-file: global.json
|
||||
|
||||
- name: Setup LLVM 17
|
||||
- name: Setup LLVM 15
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 17
|
||||
sudo ./llvm.sh 15
|
||||
|
||||
- name: Install rcodesign
|
||||
run: |
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
|
||||
<PackageVersion Include="Avalonia" Version="11.0.10" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.10" />
|
||||
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
|
||||
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
|
||||
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
|
||||
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
@@ -18,7 +18,7 @@
|
||||
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
|
||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
|
||||
<PackageVersion Include="Concentus" Version="2.2.2" />
|
||||
<PackageVersion Include="Concentus" Version="2.2.0" />
|
||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||
@@ -26,7 +26,7 @@
|
||||
<PackageVersion Include="LibHac" Version="0.19.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.1.2" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
@@ -48,11 +48,11 @@
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpMetal" Version="1.0.0-preview21" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.9" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.7" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.0" />
|
||||
|
||||
@@ -19,7 +19,7 @@ if platform.system() == "Darwin":
|
||||
else:
|
||||
OTOOL = shutil.which("llvm-otool")
|
||||
if OTOOL is None:
|
||||
for llvm_ver in [17, 16, 15, 14, 13]:
|
||||
for llvm_ver in [15, 14, 13]:
|
||||
otool_path = shutil.which(f"llvm-otool-{llvm_ver}")
|
||||
if otool_path is not None:
|
||||
OTOOL = otool_path
|
||||
|
||||
@@ -26,7 +26,7 @@ else:
|
||||
LIPO = shutil.which("llvm-lipo")
|
||||
|
||||
if LIPO is None:
|
||||
for llvm_ver in [17, 16, 15, 14, 13]:
|
||||
for llvm_ver in [15, 14, 13]:
|
||||
lipo_path = shutil.which(f"llvm-lipo-{llvm_ver}")
|
||||
if lipo_path is not None:
|
||||
LIPO = lipo_path
|
||||
|
||||
@@ -67,11 +67,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_
|
||||
|
||||
if ! [ -x "$(command -v lipo)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v llvm-lipo-17)" ];
|
||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
||||
then
|
||||
LIPO=llvm-lipo
|
||||
else
|
||||
LIPO=llvm-lipo-17
|
||||
LIPO=llvm-lipo-14
|
||||
fi
|
||||
else
|
||||
LIPO=lipo
|
||||
|
||||
@@ -62,11 +62,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTP
|
||||
|
||||
if ! [ -x "$(command -v lipo)" ];
|
||||
then
|
||||
if ! [ -x "$(command -v llvm-lipo-17)" ];
|
||||
if ! [ -x "$(command -v llvm-lipo-14)" ];
|
||||
then
|
||||
LIPO=llvm-lipo
|
||||
else
|
||||
LIPO=llvm-lipo-17
|
||||
LIPO=llvm-lipo-14
|
||||
fi
|
||||
else
|
||||
LIPO=lipo
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Common
|
||||
{
|
||||
public class RyujinxException : Exception
|
||||
{
|
||||
public RyujinxException(string message) : base(message)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
DriverId.MesaDozen => "Dozen",
|
||||
DriverId.MesaNvk => "NVK",
|
||||
DriverId.ImaginationOpenSourceMesa => "Imagination (Open)",
|
||||
DriverId.MesaHoneykrisp => "Honeykrisp",
|
||||
DriverId.MesaAgxv => "Honeykrisp",
|
||||
_ => id.ToString(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -176,7 +176,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
|
||||
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
|
||||
|
||||
if (isApplication)
|
||||
if (isApplication && lowestCpuCore == 0 && highestCpuCore != 2)
|
||||
Ryujinx.Common.Logging.Logger.Error?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}! Report this to @LotP on the Ryujinx/Ryubing discord server (discord.gg/ryujinx)!");
|
||||
else if (isApplication)
|
||||
Ryujinx.Common.Logging.Logger.Info?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}");
|
||||
|
||||
break;
|
||||
|
||||
@@ -702,18 +702,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(92)]
|
||||
// SetGestureOutputRanges(pid, ushort Unknown0)
|
||||
public ResultCode SetGestureOutputRanges(ServiceCtx context)
|
||||
{
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
ushort unknown0 = context.RequestData.ReadUInt16();
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { pid, unknown0 });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandCmif(100)]
|
||||
// SetSupportedNpadStyleSet(pid, nn::applet::AppletResourceUserId, nn::hid::NpadStyleTag)
|
||||
|
||||
@@ -26,17 +26,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
||||
|
||||
private ulong _latestPid;
|
||||
|
||||
public ProcessResult ActiveApplication
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_processesByPid.TryGetValue(_latestPid, out ProcessResult value))
|
||||
throw new RyujinxException(
|
||||
$"The HLE Process map did not have a process with ID {_latestPid}. Are you missing firmware?");
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
public ProcessResult ActiveApplication => _processesByPid[_latestPid];
|
||||
|
||||
public ProcessLoader(Switch device)
|
||||
{
|
||||
|
||||
@@ -253,11 +253,23 @@ namespace Ryujinx.Input.SDL2
|
||||
return IGamepad.GetStateSnapshot(this);
|
||||
}
|
||||
|
||||
private static bool hotButtonMinus = false;
|
||||
private static bool hotExit = false;
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
if (hotButtonMinus)
|
||||
{
|
||||
hotButtonMinus = false;
|
||||
return hotExit;
|
||||
}
|
||||
return hotExit = false;
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetMappedStateSnapshot()
|
||||
{
|
||||
GamepadStateSnapshot rawState = GetStateSnapshot();
|
||||
GamepadStateSnapshot result = default;
|
||||
|
||||
lock (_userMappingLock)
|
||||
{
|
||||
if (_buttonsUserMapping.Count == 0)
|
||||
@@ -270,6 +282,28 @@ namespace Ryujinx.Input.SDL2
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
if (GamepadButtonInputId.Minus == entry.To)
|
||||
{
|
||||
if (rawState.IsPressed(entry.From) && !hotButtonMinus)
|
||||
{
|
||||
hotButtonMinus = true;
|
||||
}
|
||||
else if (!result.IsPressed(entry.From) && hotButtonMinus)
|
||||
{
|
||||
hotButtonMinus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (GamepadButtonInputId.Plus == entry.To)
|
||||
{
|
||||
if (rawState.IsPressed(entry.To) && hotButtonMinus)
|
||||
{
|
||||
|
||||
hotExit = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Do not touch state of button already pressed
|
||||
if (!result.IsPressed(entry.To))
|
||||
{
|
||||
@@ -376,5 +410,7 @@ namespace Ryujinx.Input.SDL2
|
||||
|
||||
return SDL_GameControllerGetButton(_gamepadHandle, _buttonsDriverMapping[(int)inputId]) == 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +329,11 @@ namespace Ryujinx.Input.SDL2
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public GamepadStateSnapshot GetStateSnapshot()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
|
||||
@@ -25,6 +25,10 @@ namespace Ryujinx.Input.SDL2
|
||||
{
|
||||
_driver = driver;
|
||||
}
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Vector2 GetPosition()
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.HLE.HOS.Services.Hid;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -273,15 +274,21 @@ namespace Ryujinx.Input.HLE
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
public bool Update()
|
||||
{
|
||||
|
||||
// _gamepad may be altered by other threads
|
||||
var gamepad = _gamepad;
|
||||
|
||||
|
||||
if (gamepad != null && GamepadDriver != null)
|
||||
{
|
||||
State = gamepad.GetMappedStateSnapshot();
|
||||
|
||||
if (gamepad.SpecialExit())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion)
|
||||
{
|
||||
if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver)
|
||||
@@ -334,6 +341,7 @@ namespace Ryujinx.Input.HLE
|
||||
State = default;
|
||||
_leftMotionInput = null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public GamepadInput GetHLEInputState()
|
||||
|
||||
@@ -200,8 +200,10 @@ namespace Ryujinx.Input.HLE
|
||||
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
||||
}
|
||||
|
||||
public void Update(float aspectRatio = 1)
|
||||
public bool Update(float aspectRatio = 1)
|
||||
{
|
||||
bool specialExit = false;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
List<GamepadInput> hleInputStates = new();
|
||||
@@ -225,9 +227,10 @@ namespace Ryujinx.Input.HLE
|
||||
DriverConfigurationUpdate(ref controller, inputConfig);
|
||||
|
||||
controller.UpdateUserConfiguration(inputConfig);
|
||||
controller.Update();
|
||||
controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex));
|
||||
|
||||
specialExit = controller.Update(); //hotkey press check
|
||||
controller.UpdateRumble(_device.Hid.Npads.GetRumbleQueue(playerIndex));
|
||||
|
||||
inputState = controller.GetHLEInputState();
|
||||
|
||||
inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick);
|
||||
@@ -315,6 +318,8 @@ namespace Ryujinx.Input.HLE
|
||||
|
||||
_device.TamperMachine.UpdateInput(hleInputStates);
|
||||
}
|
||||
|
||||
return specialExit;
|
||||
}
|
||||
|
||||
internal InputConfig GetPlayerInputConfigByIndex(int index)
|
||||
|
||||
@@ -79,6 +79,12 @@ namespace Ryujinx.Input
|
||||
/// <returns>A remapped snaphost of the state of the gamepad.</returns>
|
||||
GamepadStateSnapshot GetMappedStateSnapshot();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state if the minus and plus buttons were pressed on the gamepad.
|
||||
/// </summary>
|
||||
/// <returns>returns true if the buttons were pressed.</returns>
|
||||
bool SpecialExit();
|
||||
|
||||
/// <summary>
|
||||
/// Get a snaphost of the state of the gamepad.
|
||||
/// </summary>
|
||||
|
||||
36
src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj
Normal file
36
src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj
Normal file
@@ -0,0 +1,36 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\Controller_JoyConLeft.svg" />
|
||||
<None Remove="Resources\Controller_JoyConPair.svg" />
|
||||
<None Remove="Resources\Controller_JoyConRight.svg" />
|
||||
<None Remove="Resources\Controller_ProCon.svg" />
|
||||
<None Remove="Resources\Icon_NCA.png" />
|
||||
<None Remove="Resources\Icon_NRO.png" />
|
||||
<None Remove="Resources\Icon_NSO.png" />
|
||||
<None Remove="Resources\Icon_NSP.png" />
|
||||
<None Remove="Resources\Icon_XCI.png" />
|
||||
<None Remove="Resources\Logo_Amiibo.png" />
|
||||
<None Remove="Resources\Logo_Discord.png" />
|
||||
<None Remove="Resources\Logo_GitHub.png" />
|
||||
<None Remove="Resources\Logo_Ryujinx.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscordRichPresence" />
|
||||
<PackageReference Include="DynamicData" />
|
||||
<PackageReference Include="securifybv.ShellLink" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -18,6 +18,7 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Renderer;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Views.Main;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
@@ -70,6 +71,7 @@ namespace Ryujinx.Ava
|
||||
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
||||
private const int TargetFps = 60;
|
||||
private const float VolumeDelta = 0.05f;
|
||||
static bool SpecialExit = false;
|
||||
|
||||
private static readonly Cursor _invisibleCursor = new(StandardCursorType.None);
|
||||
private readonly nint _invisibleCursorWin;
|
||||
@@ -96,6 +98,7 @@ namespace Ryujinx.Ava
|
||||
private bool _isCursorInRenderer = true;
|
||||
private bool _ignoreCursorState = false;
|
||||
|
||||
|
||||
private enum CursorStates
|
||||
{
|
||||
CursorIsHidden,
|
||||
@@ -503,10 +506,15 @@ namespace Ryujinx.Ava
|
||||
_viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
|
||||
|
||||
MainLoop();
|
||||
|
||||
|
||||
Exit();
|
||||
}
|
||||
|
||||
public bool IsSpecialExit()
|
||||
{
|
||||
return SpecialExit;
|
||||
}
|
||||
|
||||
private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args)
|
||||
{
|
||||
if (Device != null)
|
||||
@@ -589,6 +597,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
_isStopped = true;
|
||||
Stop();
|
||||
|
||||
}
|
||||
|
||||
public void DisposeContext()
|
||||
@@ -1135,6 +1144,7 @@ namespace Ryujinx.Ava
|
||||
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
|
||||
string vSyncMode = Device.VSyncMode.ToString();
|
||||
|
||||
|
||||
UpdateShaderCount();
|
||||
|
||||
if (GraphicsConfig.ResScale != 1)
|
||||
@@ -1200,7 +1210,17 @@ namespace Ryujinx.Ava
|
||||
return false;
|
||||
}
|
||||
|
||||
NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
|
||||
if (NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat()))
|
||||
{
|
||||
if (ConfigurationState.Instance.Hid.SpecialExitEmulator.Value == 1)
|
||||
{
|
||||
SpecialExit = true; // close App
|
||||
}
|
||||
if (ConfigurationState.Instance.Hid.SpecialExitEmulator.Value > 0)
|
||||
{
|
||||
_isActive = false; //close game
|
||||
}
|
||||
}
|
||||
|
||||
if (_viewModel.IsActive)
|
||||
{
|
||||
@@ -1335,6 +1355,8 @@ namespace Ryujinx.Ava
|
||||
|
||||
Device.Hid.DebugPad.Update();
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
using DiscordRPC;
|
||||
using Gommon;
|
||||
using Humanizer;
|
||||
using Humanizer.Localisation;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
@@ -46,7 +45,16 @@ namespace Ryujinx.Ava
|
||||
};
|
||||
|
||||
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
|
||||
TitleIDs.CurrentApplication.Event += (_, e) => Use(e.NewValue);
|
||||
TitleIDs.CurrentApplication.Event += (_, e) =>
|
||||
{
|
||||
if (e.NewValue)
|
||||
SwitchToPlayingState(
|
||||
ApplicationLibrary.LoadAndSaveMetaData(e.NewValue),
|
||||
Switch.Shared.Processes.ActiveApplication
|
||||
);
|
||||
else
|
||||
SwitchToMainState();
|
||||
};
|
||||
}
|
||||
|
||||
private static void Update(object sender, ReactiveEventArgs<bool> evnt)
|
||||
@@ -67,23 +75,11 @@ namespace Ryujinx.Ava
|
||||
_discordClient = new DiscordRpcClient(ApplicationId);
|
||||
|
||||
_discordClient.Initialize();
|
||||
|
||||
Use(TitleIDs.CurrentApplication);
|
||||
_discordClient.SetPresence(_discordPresenceMain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Use(Optional<string> titleId)
|
||||
{
|
||||
if (titleId.TryGet(out string tid))
|
||||
SwitchToPlayingState(
|
||||
ApplicationLibrary.LoadAndSaveMetaData(tid),
|
||||
Switch.Shared.Processes.ActiveApplication
|
||||
);
|
||||
else
|
||||
SwitchToMainState();
|
||||
}
|
||||
|
||||
private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
|
||||
{
|
||||
_discordClient?.SetPresence(new RichPresence
|
||||
|
||||
@@ -228,6 +228,8 @@ namespace Ryujinx.Headless
|
||||
_inputConfiguration ??= [];
|
||||
_enableKeyboard = option.EnableKeyboard;
|
||||
_enableMouse = option.EnableMouse;
|
||||
|
||||
|
||||
|
||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
@@ -299,10 +301,7 @@ namespace Ryujinx.Headless
|
||||
_userChannelPersistence.ShouldRestart = false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_inputManager.Dispose();
|
||||
} catch {}
|
||||
_inputManager.Dispose();
|
||||
|
||||
return;
|
||||
|
||||
@@ -339,23 +338,23 @@ namespace Ryujinx.Headless
|
||||
{
|
||||
string label = state switch
|
||||
{
|
||||
LoadState => "PTC",
|
||||
ShaderCacheState => "Shaders",
|
||||
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}")
|
||||
LoadState => $"PTC : {current}/{total}",
|
||||
ShaderCacheState => $"Shaders : {current}/{total}",
|
||||
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}"),
|
||||
};
|
||||
|
||||
Logger.Info?.Print(LogClass.Application, $"{label} : {current}/{total}");
|
||||
Logger.Info?.Print(LogClass.Application, label);
|
||||
}
|
||||
|
||||
private static WindowBase CreateWindow(Options options)
|
||||
{
|
||||
return options.GraphicsBackend switch
|
||||
{
|
||||
GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet),
|
||||
GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit),
|
||||
GraphicsBackend.Metal => OperatingSystem.IsMacOS() ?
|
||||
new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet) :
|
||||
new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit) :
|
||||
throw new Exception("Attempted to use Metal renderer on non-macOS platform!"),
|
||||
_ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet)
|
||||
_ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode, options.IgnoreControllerApplet, options.SpecialExit)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,11 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) { }
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator) { }
|
||||
|
||||
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_METAL;
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL;
|
||||
|
||||
protected override void InitializeWindowRenderer()
|
||||
{
|
||||
@@ -118,13 +118,14 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator)
|
||||
{
|
||||
_glLogLevel = glLogLevel;
|
||||
}
|
||||
|
||||
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_OPENGL;
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_OPENGL;
|
||||
|
||||
protected override void InitializeWindowRenderer()
|
||||
{
|
||||
@@ -150,7 +150,10 @@ namespace Ryujinx.Headless
|
||||
|
||||
if (NeedsOverride(nameof(IgnoreControllerApplet)))
|
||||
IgnoreControllerApplet = configurationState.IgnoreApplet;
|
||||
|
||||
|
||||
if (NeedsOverride(nameof(SpecialExit)))
|
||||
SpecialExit = configurationState.Hid.SpecialExitEmulator;
|
||||
|
||||
return;
|
||||
|
||||
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
|
||||
@@ -274,6 +277,9 @@ namespace Ryujinx.Headless
|
||||
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
||||
public bool EnableMouse { get; set; }
|
||||
|
||||
[Option("enable-press-hotkeys-to-exit", Required = false, Default = 0, HelpText = "press the minus and plus buttons to: 0 -disable, 1 - exit app, 2 - exit game.")]
|
||||
public int SpecialExit { get; set; }
|
||||
|
||||
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
||||
public HideCursorMode HideCursorMode { get; set; }
|
||||
|
||||
@@ -414,6 +420,7 @@ namespace Ryujinx.Headless
|
||||
[Option("ignore-controller-applet", Required = false, Default = false, HelpText = "Enable ignoring the controller applet when your game loses connection to your controller.")]
|
||||
public bool IgnoreControllerApplet { get; set; }
|
||||
|
||||
|
||||
// Values
|
||||
|
||||
[Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]
|
||||
|
||||
BIN
src/Ryujinx/Headless/Ryujinx.bmp
Normal file
BIN
src/Ryujinx/Headless/Ryujinx.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
@@ -18,13 +18,14 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet)
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet, specialExitEmulator)
|
||||
{
|
||||
_glLogLevel = glLogLevel;
|
||||
}
|
||||
|
||||
public override SDL_WindowFlags WindowFlags => SDL_WindowFlags.SDL_WINDOW_VULKAN;
|
||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_VULKAN;
|
||||
|
||||
protected override void InitializeWindowRenderer() { }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Humanizer;
|
||||
using LibHac.Tools.Fs;
|
||||
using Ryujinx.Ava;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
@@ -89,6 +88,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
private readonly AspectRatio _aspectRatio;
|
||||
private readonly bool _enableMouse;
|
||||
private readonly int _specialExitEmulator;
|
||||
private readonly bool _ignoreControllerApplet;
|
||||
|
||||
public WindowBase(
|
||||
@@ -97,7 +97,8 @@ namespace Ryujinx.Headless
|
||||
AspectRatio aspectRatio,
|
||||
bool enableMouse,
|
||||
HideCursorMode hideCursorMode,
|
||||
bool ignoreControllerApplet)
|
||||
bool ignoreControllerApplet,
|
||||
int specialExitEmulator)
|
||||
{
|
||||
MouseDriver = new SDL2MouseDriver(hideCursorMode);
|
||||
_inputManager = inputManager;
|
||||
@@ -113,6 +114,7 @@ namespace Ryujinx.Headless
|
||||
_gpuDoneEvent = new ManualResetEvent(false);
|
||||
_aspectRatio = aspectRatio;
|
||||
_enableMouse = enableMouse;
|
||||
_specialExitEmulator = specialExitEmulator;
|
||||
_ignoreControllerApplet = ignoreControllerApplet;
|
||||
HostUITheme = new HeadlessHostUiTheme();
|
||||
|
||||
@@ -138,7 +140,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
private void SetWindowIcon()
|
||||
{
|
||||
Stream iconStream = EmbeddedResources.GetStream("Ryujinx/Assets/UIImages/Logo_Ryujinx.png");
|
||||
Stream iconStream = typeof(Program).Assembly.GetManifestResourceStream("HeadlessLogo");
|
||||
byte[] iconBytes = new byte[iconStream!.Length];
|
||||
|
||||
if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
|
||||
@@ -192,7 +194,7 @@ namespace Ryujinx.Headless
|
||||
FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | WindowFlags);
|
||||
WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags());
|
||||
|
||||
if (WindowHandle == nint.Zero)
|
||||
{
|
||||
@@ -247,7 +249,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
protected abstract void SwapBuffers();
|
||||
|
||||
public abstract SDL_WindowFlags WindowFlags { get; }
|
||||
public abstract SDL_WindowFlags GetWindowFlags();
|
||||
|
||||
private string GetGpuDriverName()
|
||||
{
|
||||
@@ -30,6 +30,11 @@ namespace Ryujinx.Ava.Input
|
||||
public readonly Key From = from;
|
||||
}
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
|
||||
{
|
||||
_buttonsUserMapping = [];
|
||||
|
||||
@@ -13,6 +13,11 @@ namespace Ryujinx.Ava.Input
|
||||
public string Id => "0";
|
||||
public string Name => "AvaloniaMouse";
|
||||
|
||||
public bool SpecialExit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsConnected => true;
|
||||
public GamepadFeaturesFlag Features => throw new NotImplementedException();
|
||||
public bool[] Buttons => _driver.PressedButtons;
|
||||
|
||||
@@ -21,7 +21,6 @@ using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||
using Ryujinx.Headless;
|
||||
using Ryujinx.SDL2.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -244,33 +243,16 @@ namespace Ryujinx.Ava
|
||||
: $"Launch Mode: {AppDataManager.Mode}");
|
||||
}
|
||||
|
||||
internal static void ProcessUnhandledException(object sender, Exception initialException, bool isTerminating)
|
||||
internal static void ProcessUnhandledException(object sender, Exception ex, bool isTerminating)
|
||||
{
|
||||
Logger.Log log = Logger.Error ?? Logger.Notice;
|
||||
string message = $"Unhandled exception caught: {ex}";
|
||||
|
||||
List<Exception> exceptions = [];
|
||||
|
||||
if (initialException is AggregateException ae)
|
||||
{
|
||||
exceptions.AddRange(ae.InnerExceptions);
|
||||
}
|
||||
// ReSharper disable once ConstantConditionalAccessQualifier
|
||||
if (sender?.GetType()?.AsPrettyString() is { } senderName)
|
||||
log.Print(LogClass.Application, message, senderName);
|
||||
else
|
||||
{
|
||||
exceptions.Add(initialException);
|
||||
}
|
||||
|
||||
foreach (var e in exceptions)
|
||||
{
|
||||
string message = $"Unhandled exception caught: {e}";
|
||||
// ReSharper disable once ConstantConditionalAccessQualifier
|
||||
if (sender?.GetType()?.AsPrettyString() is { } senderName)
|
||||
log.Print(LogClass.Application, message, senderName);
|
||||
else
|
||||
log.PrintMsg(LogClass.Application, message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
log.PrintMsg(LogClass.Application, message);
|
||||
|
||||
if (isTerminating)
|
||||
Exit();
|
||||
|
||||
@@ -166,6 +166,7 @@
|
||||
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Light.png" />
|
||||
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
|
||||
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
|
||||
<EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Assets\locales.json" />
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
Title="Ryujinx - Waiting"
|
||||
SizeToContent="WidthAndHeight"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
mc:Ignorable="d"
|
||||
Focusable="True">
|
||||
<Grid
|
||||
|
||||
@@ -1049,6 +1049,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void InitializeGame()
|
||||
{
|
||||
|
||||
RendererHostControl.WindowCreated += RendererHost_Created;
|
||||
|
||||
AppHost.StatusUpdatedEvent += Update_StatusBar;
|
||||
@@ -1058,7 +1059,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
AppHost?.Start();
|
||||
|
||||
if (AppHost?.IsSpecialExit() == true)
|
||||
{
|
||||
Window.ForceExit();
|
||||
}
|
||||
|
||||
AppHost?.DisposeContext();
|
||||
|
||||
}
|
||||
|
||||
private async Task HandleRelaunch()
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableDockedMode { get; set; }
|
||||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
public int EnableSpecialExit { get; set; }
|
||||
public VSyncMode VSyncMode
|
||||
{
|
||||
get => _vSyncMode;
|
||||
@@ -259,6 +260,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public int OpenglDebugLevel { get; set; }
|
||||
public int MemoryMode { get; set; }
|
||||
public int BaseStyleIndex { get; set; }
|
||||
|
||||
|
||||
public int GraphicsBackendIndex
|
||||
{
|
||||
get => _graphicsBackendIndex;
|
||||
@@ -511,6 +514,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
EnableDockedMode = config.System.EnableDockedMode;
|
||||
EnableKeyboard = config.Hid.EnableKeyboard;
|
||||
EnableMouse = config.Hid.EnableMouse;
|
||||
EnableSpecialExit = config.Hid.SpecialExitEmulator.Value switch
|
||||
{
|
||||
0 => 0, // "Hotkey 'Exit' is Disabled"
|
||||
1 => 1, // "Close app. by hotkey"
|
||||
2 => 2, // "Close game by hotkey"
|
||||
_ => 0
|
||||
};
|
||||
|
||||
// Keyboard Hotkeys
|
||||
KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value);
|
||||
@@ -618,6 +628,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||
config.Hid.EnableMouse.Value = EnableMouse;
|
||||
config.Hid.SpecialExitEmulator.Value = EnableSpecialExit switch
|
||||
{
|
||||
0 => 0, // "Hotkey 'Exit' is Disabled",
|
||||
1 => 1, // "Close app. by hotkey",
|
||||
2 => 2, // "Close game by hotkey",
|
||||
_ => 0
|
||||
};
|
||||
|
||||
// Keyboard Hotkeys
|
||||
config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsInputView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
@@ -58,6 +58,20 @@
|
||||
<TextBlock
|
||||
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
||||
</CheckBox>
|
||||
<ComboBox SelectedIndex="{Binding EnableSpecialExit}"
|
||||
ToolTip.Tip="{ext:Locale SpecialExitTooltip}"
|
||||
HorizontalContentAlignment="Left"
|
||||
MinWidth="160">
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabInputDisableExitHotKey}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabInputHotkeyIsCloseApp}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabInputHotkeyIsCloseGame}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -136,12 +136,6 @@
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSwedish}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageNorwegian}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
internal readonly AvaHostUIHandler UiHandler;
|
||||
|
||||
private bool _isLoading;
|
||||
private bool _isExitWithoutConfirm = false;
|
||||
private bool _applicationsLoadedOnce;
|
||||
|
||||
private UserChannelPersistence _userChannelPersistence;
|
||||
@@ -571,11 +572,11 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit)
|
||||
if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit && !_isExitWithoutConfirm)
|
||||
{
|
||||
e.Cancel = true;
|
||||
|
||||
ConfirmExit();
|
||||
ConfirmExit();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -616,6 +617,12 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
||||
public void ForceExit()
|
||||
{
|
||||
_isExitWithoutConfirm = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ConfirmExit()
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// <summary>
|
||||
/// The current version of the file format
|
||||
/// </summary>
|
||||
public const int CurrentVersion = 59;
|
||||
public const int CurrentVersion = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Version of the configuration file format
|
||||
@@ -366,6 +366,12 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
public bool EnableMouse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to choose one of several behaviors when pressing hotkeys:
|
||||
/// 0 - Do nothing, 1 - Close the emulator application, 2 - Exit the game.
|
||||
/// </summary>
|
||||
public int SpecialExitEmulator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hotkey Keyboard Bindings
|
||||
/// </summary>
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
|
||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||
Hid.SpecialExitEmulator.Value = cff.SpecialExitEmulator;
|
||||
Hid.Hotkeys.Value = cff.Hotkeys;
|
||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||
|
||||
@@ -414,6 +415,10 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
// This was accidentally enabled by default when it was PRed. That is not what we want,
|
||||
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
|
||||
cff.IgnoreApplet = false;
|
||||
}),
|
||||
(60, static cff =>
|
||||
{
|
||||
cff.SpecialExitEmulator = 0;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -420,6 +420,13 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableMouse { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to choose one of several behaviors when pressing hotkeys:
|
||||
/// 0 - Do nothing, 1 - Close the emulator application, 2 - Exit the game.
|
||||
/// </summary>
|
||||
public ReactiveObject<int> SpecialExitEmulator { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Hotkey Keyboard Bindings
|
||||
/// </summary>
|
||||
@@ -436,6 +443,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
{
|
||||
EnableKeyboard = new ReactiveObject<bool>();
|
||||
EnableMouse = new ReactiveObject<bool>();
|
||||
SpecialExitEmulator = new ReactiveObject<int>();
|
||||
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
||||
InputConfig = new ReactiveObject<List<InputConfig>>();
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
ShowConsole = UI.ShowConsole,
|
||||
EnableKeyboard = Hid.EnableKeyboard,
|
||||
EnableMouse = Hid.EnableMouse,
|
||||
SpecialExitEmulator = Hid.SpecialExitEmulator,
|
||||
Hotkeys = Hid.Hotkeys,
|
||||
KeyboardConfig = [],
|
||||
ControllerConfig = [],
|
||||
@@ -241,6 +242,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
UI.WindowStartup.WindowMaximized.Value = false;
|
||||
Hid.EnableKeyboard.Value = false;
|
||||
Hid.EnableMouse.Value = false;
|
||||
Hid.SpecialExitEmulator.Value = 0;
|
||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVSyncMode = Key.F1,
|
||||
|
||||
Reference in New Issue
Block a user