diff --git a/CHANGELOG.md b/CHANGELOG.md index 714681d09..deec23cb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Minor: Support more Firefox variants for incognito link opening. (#5503) - Minor: Replying to a message will now display the message being replied to. (#4350, #5519) - Minor: Links can now have prefixes and suffixes such as parentheses. (#5486, #5515) +- Minor: Added support for scrolling in splits with touchscreen panning gestures. (#5524) - Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426) - Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378) - Bugfix: Fixed restricted users usernames not being clickable. (#5405) diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 7430614a9..be91e2342 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -369,6 +370,8 @@ ChannelView::ChannelView(InternalCtor /*tag*/, QWidget *parent, Split *split, this->scrollUpdateRequested(); }); + this->grabGesture(Qt::PanGesture); + // TODO: Figure out if we need this, and if so, why // StrongFocus means we can focus this event through clicking it // and tabbing to it from another widget. I don't currently know @@ -1786,8 +1789,71 @@ void ChannelView::leaveEvent(QEvent * /*event*/) this->unpause(PauseReason::Mouse); } +bool ChannelView::event(QEvent *event) +{ + if (event->type() == QEvent::Gesture) + { + if (const auto *gestureEvent = dynamic_cast(event)) + { + return this->gestureEvent(gestureEvent); + } + } + + return BaseWidget::event(event); +} + +bool ChannelView::gestureEvent(const QGestureEvent *event) +{ + if (QGesture *pan = event->gesture(Qt::PanGesture)) + { + if (const auto *gesture = dynamic_cast(pan)) + { + switch (gesture->state()) + { + case Qt::GestureStarted: { + this->isPanning_ = true; + // Remove any selections and hide tooltip while panning + this->clearSelection(); + this->tooltipWidget_->hide(); + if (this->isScrolling_) + { + this->disableScrolling(); + } + } + break; + + case Qt::GestureUpdated: { + if (this->scrollBar_->isVisible()) + { + this->scrollBar_->offset(-gesture->delta().y() * 0.1); + } + } + break; + + case Qt::GestureFinished: + case Qt::GestureCanceled: + default: { + this->clearSelection(); + this->isPanning_ = false; + } + break; + } + + return true; + } + } + + return false; +} + void ChannelView::mouseMoveEvent(QMouseEvent *event) { + if (this->isPanning_) + { + // Don't do any text selection, hovering, etc while panning + return; + } + /// Pause on hover if (float pauseTime = getSettings()->pauseOnHoverDuration; pauseTime > 0.001F) diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index e6cb7597e..a670d6e30 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -10,6 +10,7 @@ #include "widgets/TooltipWidget.hpp" #include +#include #include #include #include @@ -216,6 +217,9 @@ protected: #endif void leaveEvent(QEvent * /*event*/) override; + bool event(QEvent *event) override; + bool gestureEvent(const QGestureEvent *event); + void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; @@ -374,6 +378,7 @@ private: QTimer clickTimer_; bool isScrolling_ = false; + bool isPanning_ = false; QPointF lastMiddlePressPosition_; QPointF currentMousePosition_; QTimer scrollTimer_;