Fix many touchscreen-related problems.

This commit is contained in:
John Preston
2026-03-28 22:44:56 +07:00
parent 79d97463ec
commit 5472f97797
9 changed files with 60 additions and 38 deletions
+19 -10
View File
@@ -729,25 +729,34 @@ bool Application::eventFilter(QObject *object, QEvent *e) {
} break;
}
const auto widget = static_cast<QWidget*>(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<QMouseEvent*>(e);
_lastMouseEventSource = ev->source();
return _lastMouseEventSource == Qt::MouseEventSynthesizedBySystem;
if (ev->source() == Qt::MouseEventSynthesizedBySystem) {
const auto widget = static_cast<QWidget*>(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<QContextMenuEvent*>(e);
return ev->reason() == QContextMenuEvent::Mouse
&& _lastMouseEventSource == Qt::MouseEventSynthesizedBySystem;
return (ev->reason() == QContextMenuEvent::Mouse)
&& _lastMouseIgnored;
} break;
}
+2 -1
View File
@@ -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<Media::View::OverlayWidget> _mediaView;
const std::unique_ptr<Lang::Instance> _langpack;
@@ -5669,6 +5669,9 @@ not_null<Ui::QuickActionContext*> 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();
+15 -13
View File
@@ -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<Ui::VerticalLayout>(this));
_inner = innerList->add(object_ptr<InnerWidget>(
innerList,
_inner = _innerList->add(object_ptr<InnerWidget>(
_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<Ui::VerticalLayout*> 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<Ui::VerticalLayout*> 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<Ui::RpWidget> *raw) {
if (raw) {
_topBarSuggestion = dialogs->insert(
_topBarSuggestion = _innerList->insert(
0,
object_ptr<Ui::SlideWrap<Ui::RpWidget>>::fromRaw(raw));
_topBarSuggestion->heightValue(
@@ -213,7 +213,7 @@ private:
void setupShortcuts();
void setupStories();
void setupSwipeBack();
void setupTopBarSuggestions(not_null<Ui::VerticalLayout*> dialogs);
void setupTopBarSuggestions();
void storiesExplicitCollapse();
void collectStoriesUserpicsViews(Data::StorySourcesList list);
void storiesToggleExplicitExpand(bool expand);
@@ -338,7 +338,8 @@ private:
rpl::event_stream<bool> _openedFolderOrForumChanges;
object_ptr<Ui::ElasticScroll> _scroll;
QPointer<InnerWidget> _inner;
Ui::VerticalLayout *_innerList = nullptr;
InnerWidget *_inner = nullptr;
std::unique_ptr<Suggestions> _suggestions;
std::vector<std::unique_ptr<Suggestions>> _hidingSuggestions;
class BottomButton;
@@ -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();
}
@@ -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) {
@@ -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<QTouchEvent*> 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<QTouchEvent*> 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<QTouchEvent*> 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<QTouchEvent*> e) {
_touchTimer.cancel();
} break;
}
e->accept();
return true;
}