Compare commits

..

7 Commits

Author SHA1 Message Date
TSR Berry
b51d57b642 Fix fetch failure when iterating over PRs 2024-05-01 18:13:09 +02:00
dependabot[bot]
54c16f4052 ci: bump actions/github-script from 6 to 7
Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 18:11:17 +02:00
Andrew Glaze
65c035cdf8 Fix alt key appearing as control in settings menus (#6742) 2024-04-29 18:18:27 +01:00
Exhigh
56c5dbe557 Fix Cursor States On Windows (#6725)
* [Ava]: Fix Cursor States On Windows

It's been sometime since the last PR #5415 was made and last time i was waiting for Ava 11 to be merged before re-writing the code and along the way forgot about the PR.

Anyway this PR supersedes both #5288 and #5415, and fixes issue: #5136

* Now, the bounds for which the cursor should be detected in renderer should be accurate to any scaling / resolution, taking into account the status and the menu bar. ( This issue was partially resolved by #6450 )

* Reduced the number of times the cursor updates from per frame update to updating only when the cursor state needs to be changed.

* Fixed the issue wherein you weren't able to resize the window, because of the cursor passthrough which caused the cursor to reset from the reset icon or flicker.

* Fixed the issue caused by #6450 which caused the cursor to disappear over the submenus while cursor was set to always hide.

* Changed the cursor state to not disappear while the game is being loaded. ( Needs Feedback ).

* Removed an unused library import.

* PR feedback

* Fix excessive line breaks and whitespaces and other feedback
* Add a check before calculating cursor idle time, such that it calculates only while the cursor mode is OnIdle.

* PR Feedback

* Rework the cursor state check code block

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* PR Feedback

* A simpler version of the previous implementation.

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* PR Feedback

* PR Feedback

---------

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2024-04-28 20:21:08 -03:00
MaxLastBreath
5976a5161b Fix direct keyboard not working when using a Controller. (#6716)
* Fix direct keyboard not working when connected with a controller

- Pass KeyboardDriver to NpadController.GetHLEKeyboardInput().
- Always fetch all keyboards if Direct Keyboard is turned on.
- Remove unnecessary return null.

* Get Keyboard Inputs outside of the controller loop.

- Moved GetHLEKeyboardInput outside of the controller loop.
- Made GetHLEKeyboardInput public static from public

* Removed extra newline

* Update src/Ryujinx.Input/HLE/NpadManager.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update src/Ryujinx.Input/HLE/NpadController.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
2024-04-28 19:02:29 +02:00
riperiperi
3d4dea624d HID: Correct direct mouse deltas (#6736)
The delta position of the mouse should be the difference between the current and last position. Subtracting the last deltas doesn't really make sense.

Won't implement pointer lock for first person games, but might stop some super weird behaviour with the mouse values appearing totally random.
2024-04-28 18:55:37 +02:00
TSRBerry
89a274c6a6 ci: Replace macos-latest label with macos-13 (#6729)
Due to a change to the GitHub runner labels a few days ago (see: actions/runner#3256) our build workflows for macOS x64 didn't work anymore.
According to https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories the macos-13 label is not using arm64 yet.

Until a better solution is offered in the linked issue above, we'll keep using the macos-13 label which hopefully doesn't switch to arm64 soon.
2024-04-26 20:36:35 -03:00
13 changed files with 152 additions and 84 deletions

View File

@@ -20,7 +20,7 @@ jobs:
- { name: win-x64, os: windows-latest, zip_os_name: win_x64 }
- { name: linux-x64, os: ubuntu-latest, zip_os_name: linux_x64 }
- { name: linux-arm64, os: ubuntu-latest, zip_os_name: linux_arm64 }
- { name: osx-x64, os: macOS-latest, zip_os_name: osx_x64 }
- { name: osx-x64, os: macos-13, zip_os_name: osx_x64 }
fail-fast: false
steps:
@@ -41,12 +41,12 @@ jobs:
- name: Change config filename
run: sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Change config filename for macOS
run: sed -r -i '' 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/PRConfig\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
shell: bash
if: github.event_name == 'pull_request' && matrix.platform.os == 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os == 'macos-13'
- name: Build
run: dotnet build -c "${{ matrix.configuration }}" -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER
@@ -61,15 +61,15 @@ jobs:
- name: Publish Ryujinx
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Publish Ryujinx.Headless.SDL2
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Headless.SDL2 --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Publish Ryujinx.Gtk3
run: dotnet publish -c "${{ matrix.configuration }}" -r "${{ matrix.platform.name }}" -o ./publish_gtk -p:Version="${{ env.RYUJINX_BASE_VERSION }}" -p:DebugType=embedded -p:SourceRevisionId="${{ steps.git_short_hash.outputs.result }}" -p:ExtraDefineConstants=DISABLE_UPDATER src/Ryujinx.Gtk3 --self-contained true
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Set executable bit
run: |
@@ -83,21 +83,21 @@ jobs:
with:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_sdl2_headless
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
- name: Upload Ryujinx.Gtk3 artifact
uses: actions/upload-artifact@v4
with:
name: gtk-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_gtk
if: github.event_name == 'pull_request' && matrix.platform.os != 'macOS-latest'
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
build_macos:
name: macOS Universal (${{ matrix.configuration }})

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
steps:
- uses: actions/github-script@v6
- uses: actions/github-script@v7
with:
script: |
const {owner, repo} = context.repo;
@@ -19,7 +19,7 @@ jobs:
const pull_head_sha = '${{github.event.workflow_run.head_sha}}';
const issue_number = await (async () => {
const pulls = await github.rest.pulls.list({owner, repo});
const pulls = await github.rest.pulls.list.endpoint.merge({owner, repo});
for await (const {data} of github.paginate.iterator(pulls)) {
for (const pull of data) {
if (pull.head.sha === pull_head_sha) {
@@ -68,4 +68,4 @@ jobs:
} else {
core.info(`Creating a comment`);
await github.rest.issues.createComment({repo, owner, issue_number, body});
}
}

View File

@@ -34,7 +34,7 @@ jobs:
shell: bash
- name: Create tag
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
github.rest.git.createRef({

View File

@@ -23,8 +23,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
newState.Buttons = (MouseButton)buttons;
newState.X = mouseX;
newState.Y = mouseY;
newState.DeltaX = mouseX - previousEntry.DeltaX;
newState.DeltaY = mouseY - previousEntry.DeltaY;
newState.DeltaX = mouseX - previousEntry.X;
newState.DeltaY = mouseY - previousEntry.Y;
newState.WheelDeltaX = scrollX;
newState.WheelDeltaY = scrollY;
newState.Attributes = connected ? MouseAttribute.IsConnected : MouseAttribute.None;

View File

@@ -487,38 +487,35 @@ namespace Ryujinx.Input.HLE
return value;
}
public KeyboardInput? GetHLEKeyboardInput()
public static KeyboardInput GetHLEKeyboardInput(IGamepadDriver KeyboardDriver)
{
if (_gamepad is IKeyboard keyboard)
var keyboard = KeyboardDriver.GetGamepad("0") as IKeyboard;
KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot();
KeyboardInput hidKeyboard = new()
{
KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot();
Modifier = 0,
Keys = new ulong[0x4],
};
KeyboardInput hidKeyboard = new()
{
Modifier = 0,
Keys = new ulong[0x4],
};
foreach (HLEKeyboardMappingEntry entry in _keyMapping)
{
ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
foreach (HLEKeyboardMappingEntry entry in _keyMapping)
{
ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
}
foreach (HLEKeyboardMappingEntry entry in _keyModifierMapping)
{
int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
hidKeyboard.Modifier |= value << entry.Target;
}
return hidKeyboard;
hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
}
return null;
}
foreach (HLEKeyboardMappingEntry entry in _keyModifierMapping)
{
int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
hidKeyboard.Modifier |= value << entry.Target;
}
return hidKeyboard;
}
protected virtual void Dispose(bool disposing)
{

View File

@@ -231,11 +231,6 @@ namespace Ryujinx.Input.HLE
var altMotionState = isJoyconPair ? controller.GetHLEMotionState(true) : default;
motionState = (controller.GetHLEMotionState(), altMotionState);
if (_enableKeyboard)
{
hleKeyboardInput = controller.GetHLEKeyboardInput();
}
}
else
{
@@ -257,6 +252,11 @@ namespace Ryujinx.Input.HLE
}
}
if (!_blockInputUpdates && _enableKeyboard)
{
hleKeyboardInput = NpadController.GetHLEKeyboardInput(_keyboardDriver);
}
_device.Hid.Npads.Update(hleInputStates);
_device.Hid.Npads.UpdateSixAxis(hleMotionStates);

View File

@@ -94,6 +94,17 @@ namespace Ryujinx.Ava
private long _lastCursorMoveTime;
private bool _isCursorInRenderer = true;
private bool _ignoreCursorState = false;
private enum CursorStates
{
CursorIsHidden,
CursorIsVisible,
ForceChangeCursor
};
private CursorStates _cursorState = !ConfigurationState.Instance.Hid.EnableMouse.Value ?
CursorStates.CursorIsVisible : CursorStates.CursorIsHidden;
private bool _isStopped;
private bool _isActive;
@@ -201,23 +212,65 @@ namespace Ryujinx.Ava
private void TopLevel_PointerEnteredOrMoved(object sender, PointerEventArgs e)
{
if (!_viewModel.IsActive)
{
_isCursorInRenderer = false;
_ignoreCursorState = false;
return;
}
if (sender is MainWindow window)
{
_lastCursorMoveTime = Stopwatch.GetTimestamp();
if (ConfigurationState.Instance.HideCursor.Value == HideCursorMode.OnIdle)
{
_lastCursorMoveTime = Stopwatch.GetTimestamp();
}
var point = e.GetCurrentPoint(window).Position;
var bounds = RendererHost.EmbeddedWindow.Bounds;
var windowYOffset = bounds.Y + window.MenuBarHeight;
var windowYLimit = (int)window.Bounds.Height - window.StatusBarHeight - 1;
if (!_viewModel.ShowMenuAndStatusBar)
{
windowYOffset -= window.MenuBarHeight;
windowYLimit += window.StatusBarHeight + 1;
}
_isCursorInRenderer = point.X >= bounds.X &&
point.X <= bounds.Width + bounds.X &&
point.Y >= bounds.Y &&
point.Y <= bounds.Height + bounds.Y;
Math.Ceiling(point.X) <= (int)window.Bounds.Width &&
point.Y >= windowYOffset &&
point.Y <= windowYLimit &&
!_viewModel.IsSubMenuOpen;
_ignoreCursorState = false;
}
}
private void TopLevel_PointerExited(object sender, PointerEventArgs e)
{
_isCursorInRenderer = false;
if (sender is MainWindow window)
{
var point = e.GetCurrentPoint(window).Position;
var bounds = RendererHost.EmbeddedWindow.Bounds;
var windowYOffset = bounds.Y + window.MenuBarHeight;
var windowYLimit = (int)window.Bounds.Height - window.StatusBarHeight - 1;
if (!_viewModel.ShowMenuAndStatusBar)
{
windowYOffset -= window.MenuBarHeight;
windowYLimit += window.StatusBarHeight + 1;
}
_ignoreCursorState = (point.X == bounds.X ||
Math.Ceiling(point.X) == (int)window.Bounds.Width) &&
point.Y >= windowYOffset &&
point.Y <= windowYLimit;
}
_cursorState = CursorStates.ForceChangeCursor;
}
private void UpdateScalingFilterLevel(object sender, ReactiveEventArgs<int> e)
@@ -245,9 +298,14 @@ namespace Ryujinx.Ava
if (OperatingSystem.IsWindows())
{
SetCursor(_defaultCursorWin);
if (_cursorState != CursorStates.CursorIsHidden && !_ignoreCursorState)
{
SetCursor(_defaultCursorWin);
}
}
});
_cursorState = CursorStates.CursorIsVisible;
}
private void HideCursor()
@@ -261,6 +319,8 @@ namespace Ryujinx.Ava
SetCursor(_invisibleCursorWin);
}
});
_cursorState = CursorStates.CursorIsHidden;
}
private void SetRendererWindowSize(Size size)
@@ -523,6 +583,8 @@ namespace Ryujinx.Ava
{
_lastCursorMoveTime = Stopwatch.GetTimestamp();
}
_cursorState = CursorStates.ForceChangeCursor;
}
public async Task<bool> LoadGuestApplication()
@@ -1037,38 +1099,32 @@ namespace Ryujinx.Ava
if (_viewModel.IsActive)
{
if (_isCursorInRenderer)
bool isCursorVisible = true;
if (_isCursorInRenderer && !_viewModel.ShowLoadProgress)
{
if (ConfigurationState.Instance.Hid.EnableMouse)
if (ConfigurationState.Instance.Hid.EnableMouse.Value)
{
HideCursor();
isCursorVisible = ConfigurationState.Instance.HideCursor.Value == HideCursorMode.Never;
}
else
{
switch (ConfigurationState.Instance.HideCursor.Value)
{
case HideCursorMode.Never:
ShowCursor();
break;
case HideCursorMode.OnIdle:
if (Stopwatch.GetTimestamp() - _lastCursorMoveTime >= CursorHideIdleTime * Stopwatch.Frequency)
{
HideCursor();
}
else
{
ShowCursor();
}
break;
case HideCursorMode.Always:
HideCursor();
break;
}
isCursorVisible = ConfigurationState.Instance.HideCursor.Value == HideCursorMode.Never ||
(ConfigurationState.Instance.HideCursor.Value == HideCursorMode.OnIdle &&
Stopwatch.GetTimestamp() - _lastCursorMoveTime < CursorHideIdleTime * Stopwatch.Frequency);
}
}
else
if (_cursorState != (isCursorVisible ? CursorStates.CursorIsVisible : CursorStates.CursorIsHidden))
{
ShowCursor();
if (isCursorVisible)
{
ShowCursor();
}
else
{
HideCursor();
}
}
Dispatcher.UIThread.Post(() =>
@@ -1154,7 +1210,7 @@ namespace Ryujinx.Ava
// Touchscreen.
bool hasTouch = false;
if (_viewModel.IsActive && !ConfigurationState.Instance.Hid.EnableMouse)
if (_viewModel.IsActive && !ConfigurationState.Instance.Hid.EnableMouse.Value)
{
hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as AvaloniaMouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
}

View File

@@ -19,8 +19,8 @@ namespace Ryujinx.Ava.UI.Helpers
{ Key.ShiftRight, LocaleKeys.KeyShiftRight },
{ Key.ControlLeft, LocaleKeys.KeyControlLeft },
{ Key.ControlRight, LocaleKeys.KeyControlRight },
{ Key.AltLeft, LocaleKeys.KeyControlLeft },
{ Key.AltRight, LocaleKeys.KeyControlRight },
{ Key.AltLeft, LocaleKeys.KeyAltLeft },
{ Key.AltRight, LocaleKeys.KeyAltRight },
{ Key.WinLeft, LocaleKeys.KeyWinLeft },
{ Key.WinRight, LocaleKeys.KeyWinRight },
{ Key.Up, LocaleKeys.KeyUp },

View File

@@ -111,8 +111,5 @@ namespace Ryujinx.Ava.UI.Helpers
[LibraryImport("user32.dll", SetLastError = true)]
public static partial IntPtr SetWindowLongPtrW(IntPtr hWnd, int nIndex, IntPtr value);
[LibraryImport("user32.dll", SetLastError = true)]
public static partial IntPtr SetWindowLongW(IntPtr hWnd, int nIndex, int value);
}
}

View File

@@ -157,7 +157,7 @@ namespace Ryujinx.Ava.UI.Renderer
lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate),
style = ClassStyles.CsOwndc,
lpszClassName = Marshal.StringToHGlobalUni(_className),
hCursor = CreateArrowCursor(),
hCursor = CreateArrowCursor()
};
RegisterClassEx(ref wndClassEx);

View File

@@ -104,6 +104,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private double _windowHeight;
private bool _isActive;
private bool _isSubMenuOpen;
public ApplicationData ListSelectedApplication;
public ApplicationData GridSelectedApplication;
@@ -317,6 +318,17 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public bool IsSubMenuOpen
{
get => _isSubMenuOpen;
set
{
_isSubMenuOpen = value;
OnPropertyChanged();
}
}
public bool ShowAll
{
get => _showAll;

View File

@@ -1,4 +1,4 @@
<UserControl
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -16,7 +16,8 @@
Name="Menu"
Height="35"
Margin="0"
HorizontalAlignment="Left">
HorizontalAlignment="Left"
IsOpen="{Binding IsSubMenuOpen, Mode=OneWayToSource}">
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel Margin="0" HorizontalAlignment="Stretch" />

View File

@@ -56,6 +56,9 @@ namespace Ryujinx.Ava.UI.Windows
public static bool ShowKeyErrorOnLoad { get; set; }
public ApplicationLibrary ApplicationLibrary { get; set; }
public readonly double StatusBarHeight;
public readonly double MenuBarHeight;
public MainWindow()
{
ViewModel = new MainWindowViewModel();
@@ -74,7 +77,9 @@ namespace Ryujinx.Ava.UI.Windows
ViewModel.Title = $"Ryujinx {Program.Version}";
// NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point.
double barHeight = MenuBar.MinHeight + StatusBarView.StatusBar.MinHeight;
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
MenuBarHeight = MenuBar.MinHeight;
double barHeight = MenuBarHeight + StatusBarHeight;
Height = ((Height - barHeight) / Program.WindowScaleFactor) + barHeight;
Width /= Program.WindowScaleFactor;