early-access version 2202

This commit is contained in:
pineappleEA 2021-11-15 21:44:06 +01:00
parent e7e23d3a10
commit 89013ee4f7
20 changed files with 136 additions and 108 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 2201. This is the source code for early-access 2202.
## Legal Notice ## Legal Notice

View file

@ -58,7 +58,8 @@ u64 NativeClock::GetRTSC() {
TimePoint new_time_point{}; TimePoint new_time_point{};
TimePoint current_time_point{}; TimePoint current_time_point{};
do { do {
current_time_point.pack = time_point.pack; std::ignore = Common::AtomicCompareAndSwap(current_time_point.pack.data(), time_point.pack,
u128{0}); // comparison value doesn't matter
_mm_mfence(); _mm_mfence();
const u64 current_measure = __rdtsc(); const u64 current_measure = __rdtsc();
u64 diff = current_measure - current_time_point.inner.last_measure; u64 diff = current_measure - current_time_point.inner.last_measure;
@ -78,7 +79,9 @@ void NativeClock::Pause(bool is_paused) {
TimePoint current_time_point{}; TimePoint current_time_point{};
TimePoint new_time_point{}; TimePoint new_time_point{};
do { do {
current_time_point.pack = time_point.pack; std::ignore =
Common::AtomicCompareAndSwap(current_time_point.pack.data(), time_point.pack,
u128{0}); // comparison value doesn't matter
new_time_point.pack = current_time_point.pack; new_time_point.pack = current_time_point.pack;
_mm_mfence(); _mm_mfence();
new_time_point.inner.last_measure = __rdtsc(); new_time_point.inner.last_measure = __rdtsc();

View file

@ -362,7 +362,6 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std
return; return;
} }
LOG_ERROR(Input, "{}", analog_value.value);
switch (index) { switch (index) {
case Settings::NativeMouseWheel::X: case Settings::NativeMouseWheel::X:
device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value); device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value);
@ -377,9 +376,9 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std
void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) { void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
std::lock_guard lock{mutex}; std::lock_guard lock{mutex};
const auto stick_value = TransformToStick(callback); const auto touch_value = TransformToTouch(callback);
device_status.mouse_stick_value = stick_value; device_status.mouse_stick_value = touch_value;
if (is_configuring) { if (is_configuring) {
device_status.mouse_position_state = {}; device_status.mouse_position_state = {};
@ -387,8 +386,8 @@ void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
return; return;
} }
device_status.mouse_position_state.x = stick_value.x.value; device_status.mouse_position_state.x = touch_value.x.value;
device_status.mouse_position_state.y = stick_value.y.value; device_status.mouse_position_state.y = touch_value.y.value;
TriggerOnChange(DeviceTriggerType::Mouse); TriggerOnChange(DeviceTriggerType::Mouse);
} }
@ -421,7 +420,7 @@ MousePosition EmulatedDevices::GetMousePosition() const {
return device_status.mouse_position_state; return device_status.mouse_position_state;
} }
AnalogStickState EmulatedDevices::GetMouseDeltaWheel() const { AnalogStickState EmulatedDevices::GetMouseWheel() const {
return device_status.mouse_wheel_state; return device_status.mouse_wheel_state;
} }

View file

@ -38,7 +38,7 @@ using MouseButtonValues =
std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>; std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
using MouseAnalogValues = using MouseAnalogValues =
std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>; std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
using MouseStickValue = Common::Input::StickStatus; using MouseStickValue = Common::Input::TouchStatus;
struct MousePosition { struct MousePosition {
f32 x; f32 x;
@ -130,7 +130,7 @@ public:
MousePosition GetMousePosition() const; MousePosition GetMousePosition() const;
/// Returns the latest mouse wheel change /// Returns the latest mouse wheel change
AnalogStickState GetMouseDeltaWheel() const; AnalogStickState GetMouseWheel() const;
/** /**
* Adds a callback to the list of events * Adds a callback to the list of events

View file

@ -502,21 +502,30 @@ static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incor
// This is nn::hid::KeyboardModifier // This is nn::hid::KeyboardModifier
struct KeyboardModifier { struct KeyboardModifier {
union { union {
u64 raw{}; u32 raw{};
BitField<0, 1, u64> control; BitField<0, 1, u32> control;
BitField<1, 1, u64> shift; BitField<1, 1, u32> shift;
BitField<2, 1, u64> left_alt; BitField<2, 1, u32> left_alt;
BitField<3, 1, u64> right_alt; BitField<3, 1, u32> right_alt;
BitField<4, 1, u64> gui; BitField<4, 1, u32> gui;
BitField<8, 1, u64> caps_lock; BitField<8, 1, u32> caps_lock;
BitField<9, 1, u64> scroll_lock; BitField<9, 1, u32> scroll_lock;
BitField<10, 1, u64> num_lock; BitField<10, 1, u32> num_lock;
BitField<11, 1, u64> katakana; BitField<11, 1, u32> katakana;
BitField<12, 1, u64> hiragana; BitField<12, 1, u32> hiragana;
BitField<32, 1, u64> unknown;
}; };
}; };
static_assert(sizeof(KeyboardModifier) == 0x8, "KeyboardModifier is an invalid size");
static_assert(sizeof(KeyboardModifier) == 0x4, "KeyboardModifier is an invalid size");
// This is nn::hid::KeyboardAttribute
struct KeyboardAttribute {
union {
u32 raw{};
BitField<0, 1, u32> is_connected;
};
};
static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid size");
// This is nn::hid::KeyboardKey // This is nn::hid::KeyboardKey
struct KeyboardKey { struct KeyboardKey {
@ -555,8 +564,9 @@ struct MouseState {
s32 y; s32 y;
s32 delta_x; s32 delta_x;
s32 delta_y; s32 delta_y;
s32 delta_wheel_x; // Axis Order in HW is switched for the wheel
s32 delta_wheel_y; s32 delta_wheel_y;
s32 delta_wheel_x;
MouseButton button; MouseButton button;
MouseAttribute attribute; MouseAttribute attribute;
}; };

View file

@ -175,6 +175,10 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
case Common::Input::InputType::Touch: case Common::Input::InputType::Touch:
status = callback.touch_status; status = callback.touch_status;
break; break;
case Common::Input::InputType::Stick:
status.x = callback.stick_status.x;
status.y = callback.stick_status.y;
break;
default: default:
LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type); LOG_ERROR(Input, "Conversion from type {} to touch not implemented", callback.type);
break; break;

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <atomic>
#include "common/assert.h" #include "common/assert.h"
#include "core/hle/kernel/k_spin_lock.h" #include "core/hle/kernel/k_spin_lock.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
@ -19,7 +20,7 @@ public:
explicit KAbstractSchedulerLock(KernelCore& kernel_) : kernel{kernel_} {} explicit KAbstractSchedulerLock(KernelCore& kernel_) : kernel{kernel_} {}
bool IsLockedByCurrentThread() const { bool IsLockedByCurrentThread() const {
return owner_thread == GetCurrentThreadPointer(kernel); return owner_thread.load(std::memory_order::consume) == GetCurrentThreadPointer(kernel);
} }
void Lock() { void Lock() {
@ -38,7 +39,7 @@ public:
// Increment count, take ownership. // Increment count, take ownership.
lock_count = 1; lock_count = 1;
owner_thread = GetCurrentThreadPointer(kernel); owner_thread.store(GetCurrentThreadPointer(kernel), std::memory_order::release);
} }
} }
@ -53,7 +54,7 @@ public:
SchedulerType::UpdateHighestPriorityThreads(kernel); SchedulerType::UpdateHighestPriorityThreads(kernel);
// Note that we no longer hold the lock, and unlock the spinlock. // Note that we no longer hold the lock, and unlock the spinlock.
owner_thread = nullptr; owner_thread.store(nullptr, std::memory_order::release);
spin_lock.Unlock(); spin_lock.Unlock();
// Enable scheduling, and perform a rescheduling operation. // Enable scheduling, and perform a rescheduling operation.
@ -65,7 +66,7 @@ private:
KernelCore& kernel; KernelCore& kernel;
KAlignedSpinLock spin_lock{}; KAlignedSpinLock spin_lock{};
s32 lock_count{}; s32 lock_count{};
KThread* owner_thread{}; std::atomic<KThread*> owner_thread{};
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -42,8 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
next_state.key = keyboard_state; next_state.key = keyboard_state;
next_state.modifier = keyboard_modifier_state; next_state.modifier = keyboard_modifier_state;
// This is always enabled on HW. Check what it actually does next_state.attribute.is_connected.Assign(1);
next_state.modifier.unknown.Assign(1);
} }
keyboard_lifo.WriteNextEntry(next_state); keyboard_lifo.WriteNextEntry(next_state);

View file

@ -38,6 +38,7 @@ private:
struct KeyboardState { struct KeyboardState {
s64 sampling_number; s64 sampling_number;
Core::HID::KeyboardModifier modifier; Core::HID::KeyboardModifier modifier;
Core::HID::KeyboardAttribute attribute;
Core::HID::KeyboardKey key; Core::HID::KeyboardKey key;
}; };
static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");

View file

@ -38,15 +38,16 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
if (Settings::values.mouse_enabled) { if (Settings::values.mouse_enabled) {
const auto& mouse_button_state = emulated_devices->GetMouseButtons(); const auto& mouse_button_state = emulated_devices->GetMouseButtons();
const auto& mouse_position_state = emulated_devices->GetMousePosition(); const auto& mouse_position_state = emulated_devices->GetMousePosition();
const auto& mouse_wheel_state = emulated_devices->GetMouseDeltaWheel(); const auto& mouse_wheel_state = emulated_devices->GetMouseWheel();
next_state.attribute.is_connected.Assign(1); next_state.attribute.is_connected.Assign(1);
next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width); next_state.x = static_cast<s32>(mouse_position_state.x * Layout::ScreenUndocked::Width);
next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height); next_state.y = static_cast<s32>(mouse_position_state.y * Layout::ScreenUndocked::Height);
next_state.delta_x = next_state.x - last_entry.x; next_state.delta_x = next_state.x - last_entry.x;
next_state.delta_y = next_state.y - last_entry.y; next_state.delta_y = next_state.y - last_entry.y;
next_state.delta_wheel_x = mouse_wheel_state.x; next_state.delta_wheel_x = mouse_wheel_state.x - last_mouse_wheel_state.x;
next_state.delta_wheel_y = mouse_wheel_state.y; next_state.delta_wheel_y = mouse_wheel_state.y - last_mouse_wheel_state.y;
last_mouse_wheel_state = mouse_wheel_state;
next_state.button = mouse_button_state; next_state.button = mouse_button_state;
} }

View file

@ -14,6 +14,7 @@
namespace Core::HID { namespace Core::HID {
class EmulatedDevices; class EmulatedDevices;
struct MouseState; struct MouseState;
struct AnalogStickState;
} // namespace Core::HID } // namespace Core::HID
namespace Service::HID { namespace Service::HID {
@ -37,6 +38,7 @@ private:
static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
Core::HID::MouseState next_state{}; Core::HID::MouseState next_state{};
Core::HID::AnalogStickState last_mouse_wheel_state;
Core::HID::EmulatedDevices* emulated_devices; Core::HID::EmulatedDevices* emulated_devices;
}; };
} // namespace Service::HID } // namespace Service::HID

View file

@ -35,9 +35,9 @@ namespace Service::HID {
// Updating period for each HID device. // Updating period for each HID device.
// Period time is obtained by measuring the number of samples in a second on HW using a homebrew // Period time is obtained by measuring the number of samples in a second on HW using a homebrew
constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz)
constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
IAppletResource::IAppletResource(Core::System& system_, IAppletResource::IAppletResource(Core::System& system_,
@ -79,11 +79,11 @@ IAppletResource::IAppletResource(Core::System& system_,
const auto guard = LockService(); const auto guard = LockService();
UpdateControllers(user_data, ns_late); UpdateControllers(user_data, ns_late);
}); });
keyboard_update_event = Core::Timing::CreateEvent( mouse_keyboard_update_event = Core::Timing::CreateEvent(
"HID::UpdatekeyboardCallback", "HID::UpdateMouseKeyboardCallback",
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
const auto guard = LockService(); const auto guard = LockService();
UpdateKeyboard(user_data, ns_late); UpdateMouseKeyboard(user_data, ns_late);
}); });
motion_update_event = Core::Timing::CreateEvent( motion_update_event = Core::Timing::CreateEvent(
"HID::UpdateMotionCallback", "HID::UpdateMotionCallback",
@ -93,7 +93,7 @@ IAppletResource::IAppletResource(Core::System& system_,
}); });
system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event); system.CoreTiming().ScheduleEvent(mouse_keyboard_update_ns, mouse_keyboard_update_event);
system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
system.HIDCore().ReloadInputDevices(); system.HIDCore().ReloadInputDevices();
@ -109,7 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) {
IAppletResource::~IAppletResource() { IAppletResource::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(pad_update_event, 0); system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
system.CoreTiming().UnscheduleEvent(motion_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
} }
@ -130,6 +130,10 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) { if (controller == controllers[static_cast<size_t>(HidController::Keyboard)]) {
continue; continue;
} }
// Mouse has it's own update event
if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
continue;
}
controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(),
SHARED_MEMORY_SIZE); SHARED_MEMORY_SIZE);
} }
@ -142,18 +146,21 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
} }
void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming(); auto& core_timing = system.CoreTiming();
controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(
core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate( controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(
core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
// If ns_late is higher than the update rate ignore the delay // If ns_late is higher than the update rate ignore the delay
if (ns_late > keyboard_update_ns) { if (ns_late > mouse_keyboard_update_ns) {
ns_late = {}; ns_late = {};
} }
core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event); core_timing.ScheduleEvent(mouse_keyboard_update_ns - ns_late, mouse_keyboard_update_event);
} }
void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {

View file

@ -70,13 +70,13 @@ private:
void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
KernelHelpers::ServiceContext& service_context; KernelHelpers::ServiceContext& service_context;
std::shared_ptr<Core::Timing::EventType> pad_update_event; std::shared_ptr<Core::Timing::EventType> pad_update_event;
std::shared_ptr<Core::Timing::EventType> keyboard_update_event; std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
std::shared_ptr<Core::Timing::EventType> motion_update_event; std::shared_ptr<Core::Timing::EventType> motion_update_event;
std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)> std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>

View file

@ -7,7 +7,6 @@
#include <array> #include <array>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.h"
namespace Service::HID { namespace Service::HID {
constexpr std::size_t max_buffer_size = 17; constexpr std::size_t max_buffer_size = 17;
@ -21,7 +20,7 @@ struct AtomicStorage {
template <typename State> template <typename State>
struct Lifo { struct Lifo {
s64 timestamp{}; s64 timestamp{};
s64 total_buffer_count = max_buffer_size; s64 total_buffer_count = static_cast<s64>(max_buffer_size);
s64 buffer_tail{}; s64 buffer_tail{};
s64 buffer_count{}; s64 buffer_count{};
std::array<AtomicStorage<State>, max_buffer_size> entries{}; std::array<AtomicStorage<State>, max_buffer_size> entries{};
@ -35,11 +34,11 @@ struct Lifo {
} }
std::size_t GetPreviousEntryIndex() const { std::size_t GetPreviousEntryIndex() const {
return (buffer_tail + total_buffer_count - 1) % total_buffer_count; return static_cast<size_t>((buffer_tail + total_buffer_count - 1) % total_buffer_count);
} }
std::size_t GetNextEntryIndex() const { std::size_t GetNextEntryIndex() const {
return (buffer_tail + 1) % total_buffer_count; return static_cast<size_t>((buffer_tail + 1) % total_buffer_count);
} }
void WriteNextEntry(const State& new_state) { void WriteNextEntry(const State& new_state) {

View file

@ -486,42 +486,30 @@ std::string GCAdapter::GetUIButtonName(const Common::ParamPackage& params) const
switch (button) { switch (button) {
case PadButton::ButtonLeft: case PadButton::ButtonLeft:
return "left"; return "left";
break;
case PadButton::ButtonRight: case PadButton::ButtonRight:
return "right"; return "right";
break;
case PadButton::ButtonDown: case PadButton::ButtonDown:
return "down"; return "down";
break;
case PadButton::ButtonUp: case PadButton::ButtonUp:
return "up"; return "up";
break;
case PadButton::TriggerZ: case PadButton::TriggerZ:
return "Z"; return "Z";
break;
case PadButton::TriggerR: case PadButton::TriggerR:
return "R"; return "R";
break;
case PadButton::TriggerL: case PadButton::TriggerL:
return "L"; return "L";
break;
case PadButton::ButtonA: case PadButton::ButtonA:
return "A"; return "A";
break;
case PadButton::ButtonB: case PadButton::ButtonB:
return "B"; return "B";
break;
case PadButton::ButtonX: case PadButton::ButtonX:
return "X"; return "X";
break;
case PadButton::ButtonY: case PadButton::ButtonY:
return "Y"; return "Y";
break;
case PadButton::ButtonStart: case PadButton::ButtonStart:
return "start"; return "start";
break;
default: default:
return "Unkown GC"; return "Unknown GC";
} }
} }

View file

@ -26,6 +26,12 @@ constexpr PadIdentifier identifier = {
Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) { Mouse::Mouse(const std::string input_engine_) : InputEngine(input_engine_) {
PreSetController(identifier); PreSetController(identifier);
PreSetAxis(identifier, mouse_axis_x);
PreSetAxis(identifier, mouse_axis_y);
PreSetAxis(identifier, wheel_axis_x);
PreSetAxis(identifier, wheel_axis_y);
PreSetAxis(identifier, touch_axis_x);
PreSetAxis(identifier, touch_axis_x);
update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
} }
@ -33,7 +39,7 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
Common::SetCurrentThreadName("yuzu:input:Mouse"); Common::SetCurrentThreadName("yuzu:input:Mouse");
constexpr int update_time = 10; constexpr int update_time = 10;
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
if (Settings::values.mouse_panning) { if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
// Slow movement by 4% // Slow movement by 4%
last_mouse_change *= 0.96f; last_mouse_change *= 0.96f;
const float sensitivity = const float sensitivity =
@ -46,14 +52,17 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
StopPanning(); StopPanning();
} }
std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
// Reset wheel position
SetAxis(identifier, wheel_axis_x, 0);
SetAxis(identifier, wheel_axis_y, 0);
} }
} }
void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) { void Mouse::MouseMove(int x, int y, f32 touch_x, f32 touch_y, int center_x, int center_y) {
// If native mouse is enabled just set the screen coordinates
if (Settings::values.mouse_enabled) {
SetAxis(identifier, mouse_axis_x, touch_x);
SetAxis(identifier, mouse_axis_y, touch_y);
return;
}
SetAxis(identifier, touch_axis_x, touch_x); SetAxis(identifier, touch_axis_x, touch_x);
SetAxis(identifier, touch_axis_y, touch_y); SetAxis(identifier, touch_axis_y, touch_y);
@ -115,7 +124,7 @@ void Mouse::PressButton(int x, int y, f32 touch_x, f32 touch_y, MouseButton butt
void Mouse::ReleaseButton(MouseButton button) { void Mouse::ReleaseButton(MouseButton button) {
SetButton(identifier, static_cast<int>(button), false); SetButton(identifier, static_cast<int>(button), false);
if (!Settings::values.mouse_panning) { if (!Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
SetAxis(identifier, mouse_axis_x, 0); SetAxis(identifier, mouse_axis_x, 0);
SetAxis(identifier, mouse_axis_y, 0); SetAxis(identifier, mouse_axis_y, 0);
} }
@ -123,8 +132,10 @@ void Mouse::ReleaseButton(MouseButton button) {
} }
void Mouse::MouseWheelChange(int x, int y) { void Mouse::MouseWheelChange(int x, int y) {
SetAxis(identifier, wheel_axis_x, static_cast<f32>(x)); wheel_position.x += x;
SetAxis(identifier, wheel_axis_y, static_cast<f32>(y)); wheel_position.y += y;
SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
} }
void Mouse::ReleaseAllButtons() { void Mouse::ReleaseAllButtons() {

View file

@ -72,6 +72,7 @@ private:
Common::Vec2<int> mouse_origin; Common::Vec2<int> mouse_origin;
Common::Vec2<int> last_mouse_position; Common::Vec2<int> last_mouse_position;
Common::Vec2<float> last_mouse_change; Common::Vec2<float> last_mouse_change;
Common::Vec2<int> wheel_position;
bool button_pressed; bool button_pressed;
int mouse_panning_timout{}; int mouse_panning_timout{};
std::jthread update_thread; std::jthread update_thread;

View file

@ -604,56 +604,56 @@ int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
} }
} }
int GRenderWindow::QtModifierToSwitchModdifier(quint32 qt_moddifiers) { int GRenderWindow::QtModifierToSwitchModifier(quint32 qt_modifiers) {
int moddifier = 0; int modifier = 0;
// The values are obtained through testing, Qt doesn't seem to provide a proper enum // The values are obtained through testing, Qt doesn't seem to provide a proper enum
if ((qt_moddifiers & 0x1) != 0) { if ((qt_modifiers & 0x1) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::LeftShift; modifier |= 1 << Settings::NativeKeyboard::LeftShift;
} }
if ((qt_moddifiers & 0x2) != 0) { if ((qt_modifiers & 0x2) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::LeftControl; modifier |= 1 << Settings::NativeKeyboard::LeftControl;
} }
if ((qt_moddifiers & 0x4) != 0) { if ((qt_modifiers & 0x4) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::LeftAlt; modifier |= 1 << Settings::NativeKeyboard::LeftAlt;
} }
if ((qt_moddifiers & 0x08) != 0) { if ((qt_modifiers & 0x08) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::LeftMeta; modifier |= 1 << Settings::NativeKeyboard::LeftMeta;
} }
if ((qt_moddifiers & 0x10) != 0) { if ((qt_modifiers & 0x10) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::RightShift; modifier |= 1 << Settings::NativeKeyboard::RightShift;
} }
if ((qt_moddifiers & 0x20) != 0) { if ((qt_modifiers & 0x20) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::RightControl; modifier |= 1 << Settings::NativeKeyboard::RightControl;
} }
if ((qt_moddifiers & 0x40) != 0) { if ((qt_modifiers & 0x40) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::RightAlt; modifier |= 1 << Settings::NativeKeyboard::RightAlt;
} }
if ((qt_moddifiers & 0x80) != 0) { if ((qt_modifiers & 0x80) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::RightMeta; modifier |= 1 << Settings::NativeKeyboard::RightMeta;
} }
if ((qt_moddifiers & 0x100) != 0) { if ((qt_modifiers & 0x100) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::CapsLock; modifier |= 1 << Settings::NativeKeyboard::CapsLock;
} }
if ((qt_moddifiers & 0x200) != 0) { if ((qt_modifiers & 0x200) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::NumLock; modifier |= 1 << Settings::NativeKeyboard::NumLock;
} }
// Verify the last two keys // Verify the last two keys
if ((qt_moddifiers & 0x400) != 0) { if ((qt_modifiers & 0x400) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::Katakana; modifier |= 1 << Settings::NativeKeyboard::Katakana;
} }
if ((qt_moddifiers & 0x800) != 0) { if ((qt_modifiers & 0x800) != 0) {
moddifier |= 1 << Settings::NativeKeyboard::Hiragana; modifier |= 1 << Settings::NativeKeyboard::Hiragana;
} }
return moddifier; return modifier;
} }
void GRenderWindow::keyPressEvent(QKeyEvent* event) { void GRenderWindow::keyPressEvent(QKeyEvent* event) {
if (!event->isAutoRepeat()) { if (!event->isAutoRepeat()) {
const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers());
// Replace event->key() with event->nativeVirtualKey() since the second one provides raw key // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key
// buttons // buttons
const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier); input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier);
input_subsystem->GetKeyboard()->PressKeyboardKey(key); input_subsystem->GetKeyboard()->PressKeyboardKey(key);
// This is used for gamepads // This is used for gamepads
input_subsystem->GetKeyboard()->PressKey(event->key()); input_subsystem->GetKeyboard()->PressKey(event->key());
@ -662,9 +662,9 @@ void GRenderWindow::keyPressEvent(QKeyEvent* event) {
void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
if (!event->isAutoRepeat()) { if (!event->isAutoRepeat()) {
const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); const auto modifier = QtModifierToSwitchModifier(event->nativeModifiers());
const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); const auto key = QtKeyToSwitchKey(Qt::Key(event->key()));
input_subsystem->GetKeyboard()->SetKeyboardModifiers(moddifier); input_subsystem->GetKeyboard()->SetKeyboardModifiers(modifier);
input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key); input_subsystem->GetKeyboard()->ReleaseKeyboardKey(key);
// This is used for gamepads // This is used for gamepads
input_subsystem->GetKeyboard()->ReleaseKey(event->key()); input_subsystem->GetKeyboard()->ReleaseKey(event->key());
@ -720,7 +720,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
const int center_y = height() / 2; const int center_y = height() / 2;
input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y); input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, center_x, center_y);
if (Settings::values.mouse_panning) { if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
QCursor::setPos(mapToGlobal({center_x, center_y})); QCursor::setPos(mapToGlobal({center_x, center_y}));
} }
@ -738,8 +738,8 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
} }
void GRenderWindow::wheelEvent(QWheelEvent* event) { void GRenderWindow::wheelEvent(QWheelEvent* event) {
const int x = event->delta(); const int x = event->angleDelta().x();
const int y = 0; const int y = event->angleDelta().y();
input_subsystem->GetMouse()->MouseWheelChange(x, y); input_subsystem->GetMouse()->MouseWheelChange(x, y);
} }
@ -1035,7 +1035,7 @@ void GRenderWindow::showEvent(QShowEvent* event) {
bool GRenderWindow::eventFilter(QObject* object, QEvent* event) { bool GRenderWindow::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::HoverMove) { if (event->type() == QEvent::HoverMove) {
if (Settings::values.mouse_panning) { if (Settings::values.mouse_panning || Settings::values.mouse_enabled) {
auto* hover_event = static_cast<QMouseEvent*>(event); auto* hover_event = static_cast<QMouseEvent*>(event);
mouseMoveEvent(hover_event); mouseMoveEvent(hover_event);
return false; return false;

View file

@ -158,7 +158,7 @@ public:
static int QtKeyToSwitchKey(Qt::Key qt_keys); static int QtKeyToSwitchKey(Qt::Key qt_keys);
/// Converts a Qt modifier keys into NativeKeyboard modifier keys /// Converts a Qt modifier keys into NativeKeyboard modifier keys
static int QtModifierToSwitchModdifier(quint32 qt_moddifiers); static int QtModifierToSwitchModifier(quint32 qt_modifiers);
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override;

View file

@ -179,4 +179,6 @@ void ConfigureInputAdvanced::RetranslateUI() {
void ConfigureInputAdvanced::UpdateUIEnabled() { void ConfigureInputAdvanced::UpdateUIEnabled() {
ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked());
ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked());
} }