diff --git a/src/citron/configuration/configure_dialog.cpp b/src/citron/configuration/configure_dialog.cpp index 2819ffe33..545c8f878 100644 --- a/src/citron/configuration/configure_dialog.cpp +++ b/src/citron/configuration/configure_dialog.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "citron/configuration/configure_dialog.h" +#include #include #include #include @@ -10,8 +11,10 @@ #include #include #include +#include #include #include +#include #include "common/logging/log.h" #include "common/settings.h" #include "common/settings_enums.h" @@ -39,6 +42,50 @@ #include "citron/theme.h" #include "citron/uisettings.h" +// Event filter class to forward wheel events to scroll area's scrollbar +class ScrollAreaWheelEventFilter : public QObject { +public: + explicit ScrollAreaWheelEventFilter(QScrollArea* scroll_area, QObject* parent = nullptr, + bool prefer_horizontal = false) + : QObject(parent), scroll_area_(scroll_area), prefer_horizontal_(prefer_horizontal) {} + +protected: + bool eventFilter(QObject* obj, QEvent* event) override { + if (event->type() == QEvent::Wheel && scroll_area_) { + auto* wheel_event = static_cast(event); + const QPoint angle_delta = wheel_event->angleDelta(); + + // Determine which scrollbar to use based on scroll direction and preference + bool use_horizontal = prefer_horizontal_ || (std::abs(angle_delta.x()) > std::abs(angle_delta.y())); + + if (use_horizontal) { + // Try horizontal scrolling first + if (scroll_area_->horizontalScrollBar()->maximum() > 0) { + QApplication::sendEvent(scroll_area_->horizontalScrollBar(), wheel_event); + return true; + } + } + + // Try vertical scrolling + if (scroll_area_->verticalScrollBar()->maximum() > 0) { + QApplication::sendEvent(scroll_area_->verticalScrollBar(), wheel_event); + return true; + } + + // If vertical didn't work and we didn't try horizontal, try it now + if (!use_horizontal && scroll_area_->horizontalScrollBar()->maximum() > 0) { + QApplication::sendEvent(scroll_area_->horizontalScrollBar(), wheel_event); + return true; + } + } + return QObject::eventFilter(obj, event); + } + +private: + QScrollArea* scroll_area_; + bool prefer_horizontal_; +}; + static QScrollArea* CreateScrollArea(QWidget* widget) { auto* scroll_area = new QScrollArea(); scroll_area->setWidget(widget); @@ -46,6 +93,11 @@ static QScrollArea* CreateScrollArea(QWidget* widget) { scroll_area->setFrameShape(QFrame::NoFrame); scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + // Install event filter on the widget to forward wheel events to scrollbar + auto* filter = new ScrollAreaWheelEventFilter(scroll_area, scroll_area); + widget->installEventFilter(filter); + return scroll_area; } @@ -113,6 +165,11 @@ rainbow_timer{new QTimer(this)} { ui->setupUi(this); + // Enable wheel event scrolling on the top button scroll area (horizontal scrolling) + auto* top_button_filter = new ScrollAreaWheelEventFilter(ui->topButtonScrollArea, this, true); + ui->topButtonScrollArea->widget()->installEventFilter(top_button_filter); + ui->topButtonScrollArea->installEventFilter(top_button_filter); + last_palette_text_color = qApp->palette().color(QPalette::WindowText); if (!UISettings::values.configure_dialog_geometry.isEmpty()) { diff --git a/src/citron/configuration/configure_input_player.cpp b/src/citron/configuration/configure_input_player.cpp index 511ac5fe8..03b678c8e 100644 --- a/src/citron/configuration/configure_input_player.cpp +++ b/src/citron/configuration/configure_input_player.cpp @@ -5,12 +5,16 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include +#include #include "common/assert.h" #include "common/param_package.h" #include "configuration/qt_config.h" @@ -1536,9 +1540,56 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { } void ConfigureInputPlayer::wheelEvent(QWheelEvent* event) { - const int x = event->angleDelta().x(); - const int y = event->angleDelta().y(); - input_subsystem->GetMouse()->MouseWheelChange(x, y); + // Only handle wheel events for input mapping when in input mapping mode + // Otherwise, forward to the scroll area for scrolling + if (input_setter) { + const int x = event->angleDelta().x(); + const int y = event->angleDelta().y(); + input_subsystem->GetMouse()->MouseWheelChange(x, y); + event->accept(); + } else { + // Find the parent scroll area and forward the event to its scrollbar + // The widget hierarchy is: ConfigureInputPlayer -> QWidget (tab) -> QTabWidget -> + // ConfigureInput -> QWidget (viewport) -> QScrollArea + QWidget* current = this; + QScrollArea* scroll_area = nullptr; + + // Traverse up the parent chain to find the scroll area + while (current) { + // Check if current widget is a scroll area + if (auto* sa = qobject_cast(current)) { + scroll_area = sa; + break; + } + // Check if current widget's parent is a scroll area (for viewport case) + QWidget* parent = current->parentWidget(); + if (parent) { + if (auto* sa = qobject_cast(parent)) { + scroll_area = sa; + break; + } + } + current = parent; + } + + if (scroll_area) { + // Forward to vertical scrollbar if available + if (scroll_area->verticalScrollBar()->maximum() > 0) { + QApplication::sendEvent(scroll_area->verticalScrollBar(), event); + event->accept(); + return; + } + // Otherwise try horizontal scrollbar + if (scroll_area->horizontalScrollBar()->maximum() > 0) { + QApplication::sendEvent(scroll_area->horizontalScrollBar(), event); + event->accept(); + return; + } + } + + // If no scroll area found, let the event propagate normally + event->ignore(); + } } void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {