Compare commits

..

15 Commits

Author SHA1 Message Date
lizzie f6240ebcf3 Trigger build 2026-09-13 06:25:28 +00:00
lizzie 1a47492b08 2026-09-13 04:20:05
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 04:20:05 +00:00
lizzie 83d5c53dc0 2026-09-13 04:19:52
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 04:19:53 +00:00
lizzie 1f52d230b0 2026-09-13 04:19:20
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 04:19:21 +00:00
lizzie ae246aa03d 2026-09-13 03:47:52
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 03:47:53 +00:00
lizzie 466769f18a 2026-09-13 02:59:49
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 02:59:49 +00:00
lizzie f6cff5fb11 2026-09-13 02:30:50
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 02:30:50 +00:00
lizzie b4ea90a0a7 2026-09-13 02:30:08
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 02:30:08 +00:00
lizzie 1c0fb20ed0 2026-09-13 02:28:54
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 02:28:54 +00:00
lizzie 5ddc43e789 2026-09-13 00:57:32
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 00:58:13 +00:00
lizzie 6980056891 Trigger build 2026-09-13 00:58:13 +00:00
lizzie de28f1b45a 2026-09-05 05:55:38
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 00:58:13 +00:00
lizzie 3ab4277f21 2026-09-05 05:53:11
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 00:58:13 +00:00
lizzie 4b0eabb2bc 2026-09-04 23:59:41
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 00:58:13 +00:00
lizzie f683527045 2026-09-04 23:57:52
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-13 00:58:13 +00:00
10 changed files with 94 additions and 102 deletions
+5 -3
View File
@@ -261,7 +261,6 @@ SinkStream* CubebSink::AcquireSinkStream(Core::System& system, u32 system_channe
system_channels = system_channels_;
SinkStreamPtr& stream = sink_streams.emplace_back(std::make_unique<CubebSinkStream>(
ctx, device_channels, system_channels, output_device, input_device, name, type, system));
stream->SetDeviceVolume(device_volume);
return stream.get();
}
@@ -281,11 +280,14 @@ void CubebSink::CloseStreams() {
}
f32 CubebSink::GetDeviceVolume() const {
return device_volume;
if (sink_streams.empty()) {
return 1.0f;
}
return sink_streams[0]->GetDeviceVolume();
}
void CubebSink::SetDeviceVolume(f32 volume) {
device_volume = volume;
for (auto& stream : sink_streams) {
stream->SetDeviceVolume(volume);
}
+2 -11
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -41,7 +38,6 @@ public:
StreamType type) override {
if (null_sink == nullptr) {
null_sink = std::make_unique<NullSinkStreamImpl>(system, type);
null_sink->SetDeviceVolume(device_volume);
}
return null_sink.get();
}
@@ -49,14 +45,9 @@ public:
void CloseStream(SinkStream*) override {}
void CloseStreams() override {}
f32 GetDeviceVolume() const override {
return device_volume;
}
void SetDeviceVolume(f32 volume) override {
device_volume = volume;
if (null_sink != nullptr) {
null_sink->SetDeviceVolume(volume);
}
return 1.0f;
}
void SetDeviceVolume(f32 volume) override {}
void SetSystemVolume(f32 volume) override {}
private:
+5 -3
View File
@@ -246,7 +246,6 @@ SinkStream* SDLSink::AcquireSinkStream(Core::System& system, u32 system_channels
system_channels = system_channels_;
SinkStreamPtr& stream = sink_streams.emplace_back(std::make_unique<SDLSinkStream>(
device_channels, system_channels, output_device, input_device, type, system));
stream->SetDeviceVolume(device_volume);
return stream.get();
}
@@ -265,11 +264,14 @@ void SDLSink::CloseStreams() {
}
f32 SDLSink::GetDeviceVolume() const {
return device_volume;
if (sink_streams.empty()) {
return 1.0f;
}
return sink_streams[0]->GetDeviceVolume();
}
void SDLSink::SetDeviceVolume(f32 volume) {
device_volume = volume;
for (auto& stream : sink_streams) {
stream->SetDeviceVolume(volume);
}
-5
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -99,8 +96,6 @@ public:
}
protected:
/// Master volume, persists stream lifetimes
f32 device_volume{1.0f};
/// Number of device channels supported by the hardware
u32 device_channels{2};
/// Number of channels the game is sending
+52 -59
View File
@@ -4,17 +4,16 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
#include <chrono>
#include <fmt/ranges.h>
#include <math.h>
#include "common/param_package.h"
#include "common/settings.h"
#include "common/thread.h"
#include "common/steady_clock.h"
#include "input_common/drivers/mouse.h"
namespace InputCommon {
constexpr int update_time = 10;
constexpr float default_panning_sensitivity = 0.0010f;
constexpr float default_stick_sensitivity = 0.0006f;
constexpr float default_deadzone_counterweight = 0.01f;
@@ -74,33 +73,31 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_))
last_motion_change = {};
}
void Mouse::UpdateStickInput() {
if (!IsMousePanningEnabled()) {
return;
void Mouse::UpdateStickInput(Common::SteadyClock::time_point timestamp) {
if (IsMousePanningEnabled()) {
const float length = last_mouse_change.Length();
// Prevent input from exceeding the max range (1.0f) too much,
// but allow some room to make it easier to sustain
if (length > maximum_stick_range) {
last_mouse_change /= length;
last_mouse_change *= maximum_stick_range;
}
SetAxis(identifier, mouse_axis_x, last_mouse_change[0]);
SetAxis(identifier, mouse_axis_y, -last_mouse_change[1]);
// Decay input over time
const float clamped_length = (std::min)(1.0f, length);
const float decay_strength = Settings::values.mouse_panning_decay_strength.GetValue();
const float decay = 1 - clamped_length * clamped_length * decay_strength * 0.01f;
const float min_decay = Settings::values.mouse_panning_min_decay.GetValue();
const float clamped_decay = (std::min)(1 - min_decay / 100.0f, decay);
last_mouse_change *= clamped_decay;
}
const float length = last_mouse_change.Length();
// Prevent input from exceeding the max range (1.0f) too much,
// but allow some room to make it easier to sustain
if (length > maximum_stick_range) {
last_mouse_change /= length;
last_mouse_change *= maximum_stick_range;
}
SetAxis(identifier, mouse_axis_x, last_mouse_change[0]);
SetAxis(identifier, mouse_axis_y, -last_mouse_change[1]);
// Decay input over time
const float clamped_length = (std::min)(1.0f, length);
const float decay_strength = Settings::values.mouse_panning_decay_strength.GetValue();
const float decay = 1 - clamped_length * clamped_length * decay_strength * 0.01f;
const float min_decay = Settings::values.mouse_panning_min_decay.GetValue();
const float clamped_decay = (std::min)(1 - min_decay / 100.0f, decay);
last_mouse_change *= clamped_decay;
}
void Mouse::UpdateMotionInput() {
void Mouse::UpdateMotionInput(Common::SteadyClock::time_point timestamp) {
const float sensitivity =
IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity;
@@ -114,23 +111,21 @@ void Mouse::UpdateMotionInput() {
last_motion_change[1] = last_motion_change[1] * multiplier;
}
const BasicMotion motion_data{
.gyro_x = last_motion_change[0] * sensitivity,
.gyro_y = last_motion_change[1] * sensitivity,
.gyro_z = last_motion_change[2] * sensitivity,
.accel_x = 0,
.accel_y = 0,
.accel_z = 0,
.delta_timestamp = update_time * 1000,
};
if (IsMousePanningEnabled()) {
last_motion_change[0] = 0;
last_motion_change[1] = 0;
}
last_motion_change[2] = 0;
SetMotion(motion_identifier, 0, motion_data);
SetMotion(motion_identifier, 0, BasicMotion{
.gyro_x = last_motion_change[0] * sensitivity,
.gyro_y = last_motion_change[1] * sensitivity,
.gyro_z = last_motion_change[2] * sensitivity,
.accel_x = 0,
.accel_y = 0,
.accel_z = 0,
.delta_timestamp = u64(std::chrono::duration_cast<std::chrono::microseconds>(timestamp - last_notify_timestamp).count()),
});
}
void Mouse::Move(int x, int y, int center_x, int center_y) {
@@ -149,29 +144,27 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
last_mouse_change /= length;
last_mouse_change *= deadzone_cw;
}
return;
}
if (button_pressed) {
const auto mouse_move = Common::Vec<int, 2>(x, y) - mouse_origin;
const float x_sensitivity =
Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
const float y_sensitivity =
Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
SetAxis(identifier, mouse_axis_x, float(mouse_move[0]) * x_sensitivity);
SetAxis(identifier, mouse_axis_y, float(-mouse_move[1]) * y_sensitivity);
last_motion_change = {
float(-mouse_move[1]) * x_sensitivity,
float(-mouse_move[0]) * y_sensitivity,
last_motion_change[2],
};
} else {
if (button_pressed) {
const auto mouse_move = Common::Vec<int, 2>(x, y) - mouse_origin;
const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
SetAxis(identifier, mouse_axis_x, float(mouse_move[0]) * x_sensitivity);
SetAxis(identifier, mouse_axis_y, float(-mouse_move[1]) * y_sensitivity);
last_motion_change = {
float(-mouse_move[1]) * x_sensitivity,
float(-mouse_move[0]) * y_sensitivity,
last_motion_change[2],
};
}
}
}
void Mouse::NotifyChanged() {
UpdateStickInput();
UpdateMotionInput();
auto const timestamp = Common::SteadyClock::Now();
UpdateStickInput(timestamp);
UpdateMotionInput(timestamp);
last_notify_timestamp = timestamp;
}
void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
@@ -223,8 +216,8 @@ void Mouse::MouseWheelChange(int x, int y) {
wheel_position[0] += x;
wheel_position[1] += y;
last_motion_change[2] += static_cast<f32>(y);
SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position[0]));
SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position[1]));
SetAxis(identifier, wheel_axis_x, f32(wheel_position[0]));
SetAxis(identifier, wheel_axis_y, f32(wheel_position[1]));
}
void Mouse::ReleaseAllButtons() {
+5 -2
View File
@@ -7,7 +7,9 @@
#pragma once
#include <thread>
#include <chrono>
#include "common/steady_clock.h"
#include "common/polyfill_thread.h"
#include "common/vector_math.h"
#include "input_common/input_engine.h"
@@ -101,8 +103,8 @@ public:
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
private:
void UpdateStickInput();
void UpdateMotionInput();
void UpdateStickInput(Common::SteadyClock::time_point timestamp);
void UpdateMotionInput(Common::SteadyClock::time_point timestamp);
bool IsMousePanningEnabled();
Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
@@ -112,6 +114,7 @@ private:
Common::Vec<float, 2> last_mouse_change;
Common::Vec<float, 3> last_motion_change;
Common::Vec<int, 2> wheel_position;
Common::SteadyClock::time_point last_notify_timestamp{};
bool button_pressed = false;
};
+14 -19
View File
@@ -73,6 +73,7 @@ class QPaintEngine;
class QSurface;
constexpr int default_mouse_constrain_timeout = 10;
constexpr int default_mouse_update_timeout = 5;
class RenderWidget : public QWidget {
public:
@@ -138,6 +139,10 @@ GRenderWindow::GRenderWindow(MainWindow* parent,
mouse_constrain_timer.setInterval(default_mouse_constrain_timeout);
connect(&mouse_constrain_timer, &QTimer::timeout, this, &GRenderWindow::ConstrainMouse);
mouse_update_timer.setInterval(default_mouse_update_timeout);
connect(&mouse_update_timer, &QTimer::timeout, this, &GRenderWindow::UpdateMouse);
mouse_update_timer.start();
}
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
@@ -487,7 +492,6 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
input_subsystem->GetMouse()->PressMouseButton(button);
input_subsystem->GetMouse()->PressButton(pos.x(), pos.y(), button);
input_subsystem->GetMouse()->PressTouchButton(touch_x, touch_y, button);
input_subsystem->GetMouse()->NotifyChanged();
emit MouseActivity();
}
@@ -508,7 +512,6 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
input_subsystem->GetMouse()->MouseMove(touch_x, touch_y);
input_subsystem->GetMouse()->TouchMove(touch_x, touch_y);
input_subsystem->GetMouse()->Move(pos.x(), pos.y(), center_x, center_y);
input_subsystem->GetMouse()->NotifyChanged();
// Center mouse for mouse panning
if (Settings::values.mouse_panning && !Settings::values.mouse_enabled) {
@@ -518,8 +521,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
// Constrain mouse for mouse emulation with mouse panning
if (Settings::values.mouse_panning && Settings::values.mouse_enabled) {
const auto [clamped_mouse_x, clamped_mouse_y] = ClipToTouchScreen(x, y);
QCursor::setPos(mapToGlobal(
QPoint{static_cast<int>(clamped_mouse_x), static_cast<int>(clamped_mouse_y)}));
QCursor::setPos(mapToGlobal(QPoint{int(clamped_mouse_x), int(clamped_mouse_y)}));
}
mouse_constrain_timer.stop();
@@ -534,16 +536,10 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
const auto button = QtButtonToMouseButton(event->button());
input_subsystem->GetMouse()->ReleaseButton(button);
input_subsystem->GetMouse()->NotifyChanged();
}
void GRenderWindow::ConstrainMouse() {
if (QtCommon::emu_thread == nullptr || !Settings::values.mouse_panning) {
mouse_constrain_timer.stop();
return;
}
if (!this->isActiveWindow()) {
if (QtCommon::emu_thread == nullptr || Settings::values.mouse_panning || !this->isActiveWindow()) {
mouse_constrain_timer.stop();
return;
}
@@ -552,22 +548,22 @@ void GRenderWindow::ConstrainMouse() {
const auto pos = mapFromGlobal(QCursor::pos());
const int new_pos_x = std::clamp(pos.x(), 0, width());
const int new_pos_y = std::clamp(pos.y(), 0, height());
QCursor::setPos(mapToGlobal(QPoint{new_pos_x, new_pos_y}));
return;
} else {
const int center_x = width() / 2;
const int center_y = height() / 2;
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
}
}
const int center_x = width() / 2;
const int center_y = height() / 2;
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
void GRenderWindow::UpdateMouse() {
input_subsystem->GetMouse()->NotifyChanged(); // required to reset mouse once it's no longer moved
}
void GRenderWindow::wheelEvent(QWheelEvent* event) {
const int x = event->angleDelta().x();
const int y = event->angleDelta().y();
input_subsystem->GetMouse()->MouseWheelChange(x, y);
input_subsystem->GetMouse()->NotifyChanged();
}
void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
@@ -716,7 +712,6 @@ void GRenderWindow::focusOutEvent(QFocusEvent* event) {
input_subsystem->GetKeyboard()->ReleaseAllKeys();
input_subsystem->GetTouchScreen()->ReleaseAllTouch();
input_subsystem->GetMouse()->ReleaseAllButtons();
input_subsystem->GetMouse()->NotifyChanged();
}
void GRenderWindow::resizeEvent(QResizeEvent* event) {
+2
View File
@@ -144,6 +144,7 @@ private:
void TouchUpdateEvent(const QTouchEvent* event);
void TouchEndEvent();
void ConstrainMouse();
void UpdateMouse();
void RequestCameraCapture();
void OnCameraCapture(int requestId, const QImage& img);
@@ -184,6 +185,7 @@ private:
#endif
QTimer mouse_constrain_timer;
QTimer mouse_update_timer;
protected:
void showEvent(QShowEvent* event) override;
@@ -37,10 +37,16 @@ EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Co
SDL_SetWindowTitle(this_->render_window, title.c_str());
return 2000;
}, this);
mouse_timer = SDL_AddTimer(100, [](void *userdata, SDL_TimerID, Uint32) -> Uint32 {
auto* this_ = (EmuWindow_SDL3*)userdata;
this_->input_subsystem->GetMouse()->NotifyChanged();
return 100;
}, this);
}
EmuWindow_SDL3::~EmuWindow_SDL3() {
SDL_RemoveTimer(titlebar_timer);
SDL_RemoveTimer(mouse_timer);
system.HIDCore().UnloadInputDevices();
input_subsystem->Shutdown();
SDL_Quit();
@@ -84,6 +84,9 @@ protected:
/// Periodic changer of titlebar (independent of event loop)
SDL_TimerID titlebar_timer;
// Mouse resetter once it
SDL_TimerID mouse_timer;
/// Is the window still open?
bool is_open = true;