diff --git a/metainfo.xml b/metainfo.xml
index d971612156..bc56288915 100644
--- a/metainfo.xml
+++ b/metainfo.xml
@@ -109,6 +109,7 @@
- Fixes `scripts/install-deps.sh` for openSuSE (Tumbleweed) to install the correct dependencies.
- Fixes missing dependencies for release .deb packages (#1397).
+ - Fixes mouse scroll wheel events going into the wrong direction if Alt modifier was pressed at the same time (#394).
diff --git a/src/contour/helper.cpp b/src/contour/helper.cpp
index 6d2dcc6300..d58699214a 100644
--- a/src/contour/helper.cpp
+++ b/src/contour/helper.cpp
@@ -118,30 +118,37 @@ namespace
PixelCoordinate::Y { int(double(position.y()) * dpr) - marginTop } };
}
- int mouseWheelDelta(QWheelEvent* event) noexcept
+ void sendWheelEventForDelta(QPoint const& delta,
+ PixelCoordinate const& position,
+ vtbackend::Modifiers modifiers,
+ TerminalSession& session)
{
-#if 1
- // FIXME: Temporarily addressing a really bad Qt implementation detail
- // as tracked here:
- // https://github.com/contour-terminal/contour/issues/394
- if (event->pixelDelta().y())
- return event->pixelDelta().y();
- if (event->angleDelta().y())
- return event->angleDelta().y();
-
- return 0;
-#else
- // switch (event->orientation())
- // {
- // case Qt::Orientation::Horizontal:
- // return event->pixelDelta().x() ? event->pixelDelta().x()
- // : event->angleDelta().x();
- // case Qt::Orientation::Vertical:
- // return event->pixelDelta().y() ? event->pixelDelta().y()
- // : event->angleDelta().y();
- // }
- return event->angleDelta().y();
-#endif
+ using VTMouseButton = vtbackend::MouseButton;
+
+ session.addScrollX(delta.x());
+ session.addScrollY(delta.y());
+
+ inputLog()("[{}] Accumulate scroll with current value {}",
+ modifiers,
+ crispy::point { session.getScrollX(), session.getScrollY() });
+
+ if (std::abs(session.getScrollX()) > unbox(session.terminal().cellPixelSize().width))
+ {
+ session.sendMousePressEvent(modifiers,
+ session.getScrollX() > 0 ? VTMouseButton::WheelRight
+ : VTMouseButton::WheelLeft,
+ position);
+ session.resetScrollX();
+ }
+
+ if (std::abs(session.getScrollY()) > unbox(session.terminal().cellPixelSize().height))
+ {
+ session.sendMousePressEvent(modifiers,
+ session.getScrollY() > 0 ? VTMouseButton::WheelUp
+ : VTMouseButton::WheelDown,
+ position);
+ session.resetScrollY();
+ }
}
} // namespace
@@ -415,40 +422,37 @@ bool sendKeyEvent(QKeyEvent* event, vtbackend::KeyboardEventType eventType, Term
void sendWheelEvent(QWheelEvent* event, TerminalSession& session)
{
using VTMouseButton = vtbackend::MouseButton;
+ using vtbackend::Modifier;
- auto const xDelta = event->angleDelta().x() > 0 ? 1 : event->angleDelta().x() < 0 ? -1 : 0;
- if (xDelta)
- {
- session.addScrollX(xDelta);
- inputLog()("Accumulate x scroll with current value {} ", session.getScrollX());
- }
- if (std::abs(session.getScrollX()) > unbox(session.terminal().cellPixelSize().width))
- {
- auto const modifier = makeModifiers(event->modifiers());
- auto const button = session.getScrollX() > 0 ? VTMouseButton::WheelRight : VTMouseButton::WheelLeft;
- session.resetScrollX();
- auto const pixelPosition =
- makeMousePixelPosition(event, session.profile().margins, session.contentScale());
+ auto const modifiers = makeModifiers(event->modifiers());
- session.sendMousePressEvent(modifier, button, pixelPosition);
- event->accept();
- }
+ // NOTE: Qt is playing some weird games with the mouse wheel events, i.e. if Alt is pressed
+ // it will send horizontal wheel events instead of vertical ones. We need to compensate
+ // for that here.
- auto const yDelta = mouseWheelDelta(event);
- if (yDelta)
+ auto const pixelDelta =
+ (modifiers & Modifier::Alt) ? event->pixelDelta().transposed() : event->pixelDelta();
+
+ auto const numDegrees =
+ ((modifiers & Modifier::Alt) ? event->angleDelta().transposed() : event->angleDelta()) / 8;
+
+ auto const pixelPosition =
+ makeMousePixelPosition(event, session.profile().margins, session.contentScale());
+
+ if (!pixelDelta.isNull())
{
- session.addScrollY(yDelta);
- inputLog()("Accumulate y scroll with current value {} ", session.getScrollY());
+ sendWheelEventForDelta(pixelDelta, pixelPosition, modifiers, session);
+ event->accept();
}
- if (std::abs(session.getScrollY()) > unbox(session.terminal().cellPixelSize().height))
+ else if (!numDegrees.isNull())
{
- auto const modifier = makeModifiers(event->modifiers());
- auto const button = session.getScrollY() > 0 ? VTMouseButton::WheelUp : VTMouseButton::WheelDown;
- session.resetScrollY();
- auto const pixelPosition =
- makeMousePixelPosition(event, session.profile().margins, session.contentScale());
-
- session.sendMousePressEvent(modifier, button, pixelPosition);
+ auto const numSteps = numDegrees / 15;
+ auto const cellSize = session.terminal().cellPixelSize();
+ auto const scaledDelta = QPoint {
+ numSteps.x() * unbox(cellSize.width),
+ numSteps.y() * unbox(cellSize.height),
+ };
+ sendWheelEventForDelta(scaledDelta, pixelPosition, modifiers, session);
event->accept();
}
}