From 5472f977971cc34c8b49668eaeaa54219656bace Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 28 Mar 2026 22:44:56 +0700 Subject: [PATCH] Fix many touchscreen-related problems. --- Telegram/SourceFiles/core/application.cpp | 29 ++++++++++++------- Telegram/SourceFiles/core/application.h | 3 +- .../dialogs/dialogs_inner_widget.cpp | 3 ++ .../SourceFiles/dialogs/dialogs_widget.cpp | 28 +++++++++--------- Telegram/SourceFiles/dialogs/dialogs_widget.h | 5 ++-- .../admin_log/history_admin_log_inner.cpp | 4 +++ .../history/history_inner_widget.cpp | 12 ++++---- .../media/view/media_view_overlay_widget.cpp | 12 +++++--- Telegram/lib_ui | 2 +- 9 files changed, 60 insertions(+), 38 deletions(-) diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 3f2b4645a4..9f9ad8fda7 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -729,25 +729,34 @@ bool Application::eventFilter(QObject *object, QEvent *e) { } break; } - const auto widget = static_cast(object); - if (!object->isWidgetType() - || !widget->testAttribute(Qt::WA_AcceptTouchEvents)) { - return QObject::eventFilter(object, e); - } - switch (e->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: { + _lastTouchToWidget = object->isWidgetType(); + } break; + case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: { const auto ev = static_cast(e); - _lastMouseEventSource = ev->source(); - return _lastMouseEventSource == Qt::MouseEventSynthesizedBySystem; + if (ev->source() == Qt::MouseEventSynthesizedBySystem) { + const auto widget = static_cast(object); + if (_lastTouchToWidget + || (object->isWidgetType() + && widget->testAttribute(Qt::WA_AcceptTouchEvents))) { + _lastMouseIgnored = true; + return true; + } + } + _lastMouseIgnored = false; } break; + case QEvent::ContextMenu: { const auto ev = static_cast(e); - return ev->reason() == QContextMenuEvent::Mouse - && _lastMouseEventSource == Qt::MouseEventSynthesizedBySystem; + return (ev->reason() == QContextMenuEvent::Mouse) + && _lastMouseIgnored; } break; } diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index 25e0fbbd9d..378d9b6a3d 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -433,7 +433,8 @@ private: Window::Controller *_lastActiveWindow = nullptr; Window::Controller *_lastActivePrimaryWindow = nullptr; Window::Controller *_windowInSettings = nullptr; - Qt::MouseEventSource _lastMouseEventSource = Qt::MouseEventNotSynthesized; + bool _lastMouseIgnored = false; + bool _lastTouchToWidget = false; std::unique_ptr _mediaView; const std::unique_ptr _langpack; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 43aac5203d..baa9fb1c6c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -5669,6 +5669,9 @@ not_null InnerWidget::ensureQuickAction(int64 key) { int64 InnerWidget::calcSwipeKey(int top) { top -= dialogsOffset(); + if (top < 0) { + return 0; + } for (auto it = _shownList->begin(); it != _shownList->end(); ++it) { const auto row = it->get(); const auto from = row->top(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index ac9bc088a6..ec971de510 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -383,10 +383,10 @@ Widget::Widget( _scroll->setOverscrollTypes( _stories ? OverscrollType::Virtual : OverscrollType::Real, OverscrollType::Real); - const auto innerList = _scroll->setOwnedWidget( + _innerList = _scroll->setOwnedWidget( object_ptr(this)); - _inner = innerList->add(object_ptr( - innerList, + _inner = _innerList->add(object_ptr( + _innerList, controller, rpl::combine( _childListPeerId.value(), @@ -396,13 +396,13 @@ Widget::Widget( _scroll->heightValue(), _topBarSuggestionHeightChanged.events_starting_with(0) ) | rpl::on_next([=](int height, int topBarHeight) { - innerList->setMinimumHeight(height); + _innerList->setMinimumHeight(height); _inner->setMinimumHeight(height - topBarHeight); _inner->refresh(); - }, innerList->lifetime()); + }, _innerList->lifetime()); _scroll->widthValue() | rpl::on_next([=](int width) { - innerList->resizeToWidth(width); - }, innerList->lifetime()); + _innerList->resizeToWidth(width); + }, _innerList->lifetime()); _scrollToTop->raise(); _lockUnlock->toggle(false, anim::type::instant); @@ -723,7 +723,7 @@ Widget::Widget( } setupFrozenAccountBar(); - setupTopBarSuggestions(innerList); + setupTopBarSuggestions(); } void Widget::setupSwipeBack() { @@ -737,6 +737,7 @@ void Widget::setupSwipeBack() { }; auto update = [=](Ui::Controls::SwipeContextData data) { + data.cursorTop -= _inner->y(); if (data.translation != 0) { if (data.translation < 0 && _inner @@ -771,6 +772,7 @@ void Widget::setupSwipeBack() { }; auto init = [=](int top, Qt::LayoutDirection direction) { + top -= _inner->y(); _swipeBackIconMirrored = false; _swipeBackMirrored = false; if (_childListShown.current()) { @@ -863,7 +865,7 @@ void Widget::setupSwipeBack() { }; Ui::Controls::SetupSwipeHandler({ - .widget = _inner, + .widget = _innerList, .scroll = _scroll.data(), .update = std::move(update), .init = std::move(init), @@ -1081,12 +1083,12 @@ void Widget::setupFrozenAccountBar() { }, lifetime()); } -void Widget::setupTopBarSuggestions(not_null dialogs) { +void Widget::setupTopBarSuggestions() { if (_layout == Layout::Child) { return; } using namespace rpl::mappers; - crl::on_main(dialogs, [=] { + crl::on_main(_innerList, [=] { const auto owner = &session().data(); session().api().authorizations().unreviewedChanges( ) | rpl::on_next([=] { @@ -1117,11 +1119,11 @@ void Widget::setupTopBarSuggestions(not_null dialogs) { && !searchInPeer && (id == owner->chatsFilters().defaultId()); }); - return TopBarSuggestionValue(dialogs, &session(), std::move(on)); + return TopBarSuggestionValue(_innerList, &session(), std::move(on)); }) | rpl::flatten_latest() | rpl::on_next([=]( Ui::SlideWrap *raw) { if (raw) { - _topBarSuggestion = dialogs->insert( + _topBarSuggestion = _innerList->insert( 0, object_ptr>::fromRaw(raw)); _topBarSuggestion->heightValue( diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index c43ffd67da..d379e7e304 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -213,7 +213,7 @@ private: void setupShortcuts(); void setupStories(); void setupSwipeBack(); - void setupTopBarSuggestions(not_null dialogs); + void setupTopBarSuggestions(); void storiesExplicitCollapse(); void collectStoriesUserpicsViews(Data::StorySourcesList list); void storiesToggleExplicitExpand(bool expand); @@ -338,7 +338,8 @@ private: rpl::event_stream _openedFolderOrForumChanges; object_ptr _scroll; - QPointer _inner; + Ui::VerticalLayout *_innerList = nullptr; + InnerWidget *_inner = nullptr; std::unique_ptr _suggestions; std::vector> _hidingSuggestions; class BottomButton; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index c733b9a301..eab916fe79 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -2230,6 +2230,9 @@ void InnerWidget::onTouchScrollTimer() { int32 elapsed = int32(nowTime - _touchTime); QPoint delta = _touchSpeed * elapsed / 1000; bool hasScrolled = !delta.isNull(); + if (hasScrolled) { + _scrollToSignal.fire_copy(_visibleTop - delta.y()); + } if (_touchSpeed.isNull() || !hasScrolled) { _touchScrollState = Ui::TouchScrollState::Manual; @@ -2431,6 +2434,7 @@ void InnerWidget::touchEvent(QTouchEvent *e) { void InnerWidget::touchScrollUpdated(const QPoint &screenPos) { _touchPos = screenPos; + _scrollToSignal.fire_copy(_visibleTop - (_touchPos - _touchPrevPos).y()); touchUpdateSpeed(); } diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index fe9caf683b..2dec94e730 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1617,10 +1617,13 @@ HistoryInner::VideoUserpic *HistoryInner::validateVideoUserpic( void HistoryInner::onTouchScrollTimer() { auto nowTime = crl::now(); - if (_touchScrollState == Ui::TouchScrollState::Acceleration && _touchWaitingAcceleration && (nowTime - _touchAccelerationTime) > 40) { + if (_touchScrollState == Ui::TouchScrollState::Acceleration + && _touchWaitingAcceleration + && (nowTime - _touchAccelerationTime) > 40) { _touchScrollState = Ui::TouchScrollState::Manual; touchResetSpeed(); - } else if (_touchScrollState == Ui::TouchScrollState::Auto || _touchScrollState == Ui::TouchScrollState::Acceleration) { + } else if (_touchScrollState == Ui::TouchScrollState::Auto + || _touchScrollState == Ui::TouchScrollState::Acceleration) { int32 elapsed = int32(nowTime - _touchTime); QPoint delta = _touchSpeed * elapsed / 1000; const auto consumedHorizontal = consumeScrollAction(delta); @@ -1755,11 +1758,6 @@ void HistoryInner::touchEvent(QTouchEvent *e) { } break; case QEvent::TouchUpdate: { - LOG(("UPDATE: %1,%2 -> %3,%4" - ).arg(_touchStart.x() - ).arg(_touchStart.y() - ).arg(_touchPos.x() - ).arg(_touchPos.y())); if (!_touchInProgress) { return; } else if (_touchSelect) { diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index e2aba9ed0f..fad1e36d02 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -2856,7 +2856,7 @@ void OverlayWidget::toggleFullScreen(bool fullscreen) { } void OverlayWidget::activateControls() { - if (!_menu && !_mousePressed && !_stories) { + if (!_menu && !_mousePressed && !_touchMove && !_stories) { _controlsHideTimer.callOnce(st::mediaviewWaitHide); } if (_fullScreenVideo) { @@ -2886,7 +2886,8 @@ void OverlayWidget::hideControls(bool force) { && _streamed->controls && _streamed->controls->hasMenu()) || _menu - || _mousePressed) { + || _mousePressed + || _touchMove) { return; } } @@ -7149,8 +7150,8 @@ bool OverlayWidget::handleTouchEvent(not_null e) { return false; } else if (e->type() == QEvent::TouchBegin && !e->touchPoints().isEmpty() - && _body->childAt( - _body->mapFromGlobal( + && _widget->childAt( + _widget->mapFromGlobal( e->touchPoints().cbegin()->screenPos().toPoint()))) { return false; } @@ -7163,6 +7164,7 @@ bool OverlayWidget::handleTouchEvent(not_null e) { _touchPress = true; _touchMove = _touchRightButton = false; _touchStart = e->touchPoints().cbegin()->screenPos().toPoint(); + activateControls(); } break; case QEvent::TouchUpdate: { @@ -7172,6 +7174,7 @@ bool OverlayWidget::handleTouchEvent(not_null e) { if (!_touchMove && (e->touchPoints().cbegin()->screenPos().toPoint() - _touchStart).manhattanLength() >= QApplication::startDragDistance()) { _touchMove = true; } + activateControls(); } break; case QEvent::TouchEnd: { @@ -7209,6 +7212,7 @@ bool OverlayWidget::handleTouchEvent(not_null e) { _touchTimer.cancel(); } break; } + e->accept(); return true; } diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 5e4e5043c0..07964a7b49 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 5e4e5043c0437ff7009fcdbd96cf33c917d55d86 +Subproject commit 07964a7b496d8da2f7f10ebe731f70f9ae2b6b05