From 4df5372dab24d5d459c8a14f1059dd96e5b761e1 Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Thu, 30 May 2024 22:33:24 +0400 Subject: [PATCH] Support chat preview on touchscreens. --- .../dialogs/dialogs_inner_widget.cpp | 44 +++++++++++++++++++ .../dialogs/dialogs_inner_widget.h | 8 ++++ .../SourceFiles/dialogs/dialogs_widget.cpp | 13 ++++++ Telegram/SourceFiles/dialogs/dialogs_widget.h | 1 + Telegram/lib_ui | 2 +- 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index f90993a19..7633e4d2f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1316,6 +1316,9 @@ void InnerWidget::paintSearchInTopic( } void InnerWidget::mouseMoveEvent(QMouseEvent *e) { + if (_chatPreviewTouchGlobal) { + return; + } const auto globalPosition = e->globalPos(); if (!_lastMousePosition) { _lastMousePosition = globalPosition; @@ -1333,6 +1336,8 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) { void InnerWidget::cancelChatPreview() { _chatPreviewTimer.cancel(); _chatPreviewWillBeFor = {}; + _chatPreviewTouchLocal = {}; + _chatPreviewTouchGlobal = {}; } void InnerWidget::clearIrrelevantState() { @@ -2396,10 +2401,14 @@ void InnerWidget::fillArchiveSearchMenu(not_null<Ui::PopupMenu*> menu) { void InnerWidget::showChatPreview(bool onlyUserpic) { const auto key = base::take(_chatPreviewWillBeFor); + const auto touchGlobal = base::take(_chatPreviewTouchGlobal); cancelChatPreview(); if (!pressShowsPreview(onlyUserpic) || key != computeChatPreviewRow()) { return; } + if (onlyUserpic && touchGlobal) { + _touchCancelRequests.fire({}); + } ClickHandler::unpressed(); mousePressReleased(QCursor::pos(), Qt::NoButton, Qt::NoModifier); @@ -2538,6 +2547,41 @@ void InnerWidget::parentGeometryChanged() { } } +void InnerWidget::processTouchEvent(not_null<QTouchEvent*> e) { + const auto point = e->touchPoints().empty() + ? std::optional<QPoint>() + : e->touchPoints().front().screenPos().toPoint(); + switch (e->type()) { + case QEvent::TouchBegin: { + if (!point) { + return; + } + selectByMouse(*point); + const auto onlyUserpic = true; + if (pressShowsPreview(onlyUserpic)) { + _chatPreviewTouchGlobal = point; + _chatPreviewWillBeFor = computeChatPreviewRow(); + _chatPreviewTimer.callOnce(kChatPreviewDelay); + } + } break; + + case QEvent::TouchUpdate: { + if (!_chatPreviewTouchGlobal || !point) { + return; + } + const auto delta = (*_chatPreviewTouchGlobal - *point); + if (delta.manhattanLength() > _st->photoSize) { + cancelChatPreview(); + } + } break; + + case QEvent::TouchEnd: + case QEvent::TouchCancel: if (_chatPreviewTouchGlobal) { + cancelChatPreview(); + } break; + } +} + void InnerWidget::applySearchState(SearchState state) { if (_searchState == state) { return; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index b41a4aeb3..ed94e0b58 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -174,6 +174,11 @@ public: void parentGeometryChanged(); + void processTouchEvent(not_null<QTouchEvent*> e); + [[nodiscard]] rpl::producer<> touchCancelRequests() const { + return _touchCancelRequests.events(); + } + protected: void visibleTopBottomUpdated( int visibleTop, @@ -520,6 +525,9 @@ private: base::Timer _chatPreviewTimer; Key _chatPreviewWillBeFor; Key _chatPreviewKey; + std::optional<QPoint> _chatPreviewTouchLocal; + std::optional<QPoint> _chatPreviewTouchGlobal; + rpl::event_stream<> _touchCancelRequests; rpl::variable<ChildListShown> _childListShown; float64 _narrowRatio = 0.; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index b3b5a31f9..092f2f4cc 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -473,6 +473,7 @@ Widget::Widget( updateSearchFromVisibility(true); setupSupportMode(); setupScrollUpButton(); + setupTouchChatPreview(); const auto overscrollBg = [=] { return anim::color( @@ -655,6 +656,18 @@ void Widget::setupScrollUpButton() { updateScrollUpVisibility(); } +void Widget::setupTouchChatPreview() { + _scroll->setCustomTouchProcess([=](not_null<QTouchEvent*> e) { + _inner->processTouchEvent(e); + return false; + }); + _inner->touchCancelRequests() | rpl::start_with_next([=] { + QTouchEvent ev(QEvent::TouchCancel); + ev.setTimestamp(crl::now()); + QGuiApplication::sendEvent(_scroll, &ev); + }, _inner->lifetime()); +} + void Widget::setupMoreChatsBar() { if (_layout == Layout::Child) { return; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index ec604f61c..d7e8edaeb 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -179,6 +179,7 @@ private: [[nodiscard]] const std::vector<Data::ReactionId> &searchInTags() const; void setupSupportMode(); + void setupTouchChatPreview(); void setupConnectingWidget(); void setupMainMenuToggle(); void setupMoreChatsBar(); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 495ea0af5..33aac93b1 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 495ea0af50da469fb30769ac2d78251e4279a746 +Subproject commit 33aac93b160d4cd30119c8859de722e28512902b