diff --git a/ui/widgets/scroll_area.cpp b/ui/widgets/scroll_area.cpp index 1c1ed76..8fcee09 100644 --- a/ui/widgets/scroll_area.cpp +++ b/ui/widgets/scroll_area.cpp @@ -475,32 +475,27 @@ void ScrollArea::touchResetSpeed() { _touchPrevPosValid = false; } -bool ScrollArea::eventFilter(QObject *obj, QEvent *e) { - bool res = QScrollArea::eventFilter(obj, e); - if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { - QTouchEvent *ev = static_cast(e); - if (_touchEnabled && ev->device()->type() == base::TouchDevice::TouchScreen) { - if (obj == widget()) { - touchEvent(ev); - return true; - } - } +bool ScrollArea::eventHook(QEvent *e) { + const auto was = (e->type() == QEvent::LayoutRequest) + ? verticalScrollBar()->minimum() + : 0; + const auto result = RpWidgetBase::eventHook(e); + if (was) { + // Because LayoutRequest resets custom-set minimum allowed value. + verticalScrollBar()->setMinimum(was); } - return res; + return result; +} + +bool ScrollArea::eventFilter(QObject *obj, QEvent *e) { + const auto result = QScrollArea::eventFilter(obj, e); + return (obj == widget() && filterOutTouchEvent(e)) || result; } bool ScrollArea::viewportEvent(QEvent *e) { - const auto type = e->type(); - if (type == QEvent::TouchBegin - || type == QEvent::TouchUpdate - || type == QEvent::TouchEnd - || type == QEvent::TouchCancel) { - QTouchEvent *ev = static_cast(e); - if (_touchEnabled && ev->device()->type() == base::TouchDevice::TouchScreen) { - touchEvent(ev); - return true; - } - } else if (type == QEvent::Wheel) { + if (filterOutTouchEvent(e)) { + return true; + } else if (e->type() == QEvent::Wheel) { if (_customWheelProcess && _customWheelProcess(static_cast(e))) { return true; @@ -509,6 +504,24 @@ bool ScrollArea::viewportEvent(QEvent *e) { return QScrollArea::viewportEvent(e); } +bool ScrollArea::filterOutTouchEvent(QEvent *e) { + const auto type = e->type(); + if (type == QEvent::TouchBegin + || type == QEvent::TouchUpdate + || type == QEvent::TouchEnd + || type == QEvent::TouchCancel) { + const auto ev = static_cast(e); + if (_customTouchProcess && _customTouchProcess(ev)) { + return true; + } else if (_touchEnabled + && ev->device()->type() == base::TouchDevice::TouchScreen) { + touchEvent(ev); + return true; + } + } + return false; +} + void ScrollArea::touchEvent(QTouchEvent *e) { if (!e->touchPoints().isEmpty()) { _touchPrevPos = _touchPos; @@ -624,9 +637,12 @@ void ScrollArea::scrollContentsBy(int dx, int dy) { } bool ScrollArea::touchScroll(const QPoint &delta) { - int32 scTop = scrollTop(), scMax = scrollTopMax(), scNew = std::clamp(scTop - delta.y(), 0, scMax); - if (scNew == scTop) return false; - + const auto scTop = scrollTop(); + const auto scMax = scrollTopMax(); + const auto scNew = std::clamp(scTop - delta.y(), 0, scMax); + if (scNew == scTop) { + return false; + } scrollToY(scNew); return true; } diff --git a/ui/widgets/scroll_area.h b/ui/widgets/scroll_area.h index 8df7e30..b1d03a2 100644 --- a/ui/widgets/scroll_area.h +++ b/ui/widgets/scroll_area.h @@ -175,12 +175,16 @@ public: void setCustomWheelProcess(Fn)> process) { _customWheelProcess = std::move(process); } + void setCustomTouchProcess(Fn)> process) { + _customTouchProcess = std::move(process); + } [[nodiscard]] rpl::producer<> scrolls() const; [[nodiscard]] rpl::producer<> innerResizes() const; [[nodiscard]] rpl::producer<> geometryChanged() const; protected: + bool eventHook(QEvent *e) override; bool eventFilter(QObject *obj, QEvent *e) override; void resizeEvent(QResizeEvent *e) override; @@ -197,8 +201,7 @@ private: void doSetOwnedWidget(object_ptr widget); object_ptr doTakeWidget(); - void setWidget(QWidget *widget); - + bool filterOutTouchEvent(QEvent *e); void touchScrollTimer(); bool touchScroll(const QPoint &delta); void touchScrollUpdated(const QPoint &screenPos); @@ -232,6 +235,7 @@ private: base::Timer _touchScrollTimer; Fn)> _customWheelProcess; + Fn)> _customTouchProcess; bool _widgetAcceptsTouch = false; object_ptr _widget = { nullptr };