mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 21:27:07 +02:00
Improve touchscreen swipt-to-reply.
This commit is contained in:
parent
8d0f66d562
commit
b82fa3112c
7 changed files with 77 additions and 19 deletions
|
@ -640,7 +640,7 @@ void HistoryInner::setupSwipeReply() {
|
|||
return false;
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}, _touchMaybeSelecting.value());
|
||||
}
|
||||
|
||||
bool HistoryInner::hasSelectRestriction() const {
|
||||
|
@ -1497,6 +1497,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
|
|||
_touchScroll = _touchSelect = false;
|
||||
_horizontalScrollLocked = false;
|
||||
_touchScrollState = Ui::TouchScrollState::Manual;
|
||||
_touchMaybeSelecting = false;
|
||||
mouseActionCancel();
|
||||
return;
|
||||
}
|
||||
|
@ -1519,6 +1520,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
|
|||
_touchInProgress = true;
|
||||
_horizontalScrollLocked = false;
|
||||
if (_touchScrollState == Ui::TouchScrollState::Auto) {
|
||||
_touchMaybeSelecting = false;
|
||||
_touchScrollState = Ui::TouchScrollState::Acceleration;
|
||||
_touchWaitingAcceleration = true;
|
||||
_touchAccelerationTime = crl::now();
|
||||
|
@ -1526,6 +1528,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
|
|||
_touchStart = _touchPos;
|
||||
} else {
|
||||
_touchScroll = false;
|
||||
_touchMaybeSelecting = true;
|
||||
_touchSelectTimer.callOnce(QApplication::startDragTime());
|
||||
}
|
||||
_touchSelect = false;
|
||||
|
@ -1539,6 +1542,7 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
|
|||
mouseActionUpdate(_touchPos);
|
||||
} else if (!_touchScroll && (_touchPos - _touchStart).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
_touchSelectTimer.cancel();
|
||||
_touchMaybeSelecting = false;
|
||||
_touchScroll = true;
|
||||
touchUpdateSpeed();
|
||||
}
|
||||
|
@ -1560,11 +1564,18 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
|
|||
return;
|
||||
}
|
||||
_touchInProgress = false;
|
||||
const auto notMoved = (_touchPos - _touchStart).manhattanLength()
|
||||
< QApplication::startDragDistance();
|
||||
auto weak = Ui::MakeWeak(this);
|
||||
if (_touchSelect) {
|
||||
mouseActionFinish(_touchPos, Qt::RightButton);
|
||||
QContextMenuEvent contextMenu(QContextMenuEvent::Mouse, mapFromGlobal(_touchPos), _touchPos);
|
||||
showContextMenu(&contextMenu, true);
|
||||
if (notMoved || _touchMaybeSelecting.current()) {
|
||||
mouseActionFinish(_touchPos, Qt::RightButton);
|
||||
auto contextMenu = QContextMenuEvent(
|
||||
QContextMenuEvent::Mouse,
|
||||
mapFromGlobal(_touchPos),
|
||||
_touchPos);
|
||||
showContextMenu(&contextMenu, true);
|
||||
}
|
||||
_touchScroll = false;
|
||||
} else if (_touchScroll) {
|
||||
if (_touchScrollState == Ui::TouchScrollState::Manual) {
|
||||
|
@ -1582,12 +1593,13 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
|
|||
_touchWaitingAcceleration = false;
|
||||
_touchPrevPosValid = false;
|
||||
}
|
||||
} else { // One short tap is like left mouse click.
|
||||
} else if (notMoved) { // One short tap is like left mouse click.
|
||||
mouseActionStart(_touchPos, Qt::LeftButton);
|
||||
mouseActionFinish(_touchPos, Qt::LeftButton);
|
||||
}
|
||||
if (weak) {
|
||||
_touchSelectTimer.cancel();
|
||||
_touchMaybeSelecting = false;
|
||||
_touchSelect = false;
|
||||
}
|
||||
} break;
|
||||
|
@ -3789,6 +3801,7 @@ MessageIdsList HistoryInner::getSelectedItems() const {
|
|||
|
||||
void HistoryInner::onTouchSelect() {
|
||||
_touchSelect = true;
|
||||
_touchMaybeSelecting = true;
|
||||
mouseActionStart(_touchPos, Qt::LeftButton);
|
||||
}
|
||||
|
||||
|
|
|
@ -513,6 +513,7 @@ private:
|
|||
bool _touchSelect = false;
|
||||
bool _touchInProgress = false;
|
||||
QPoint _touchStart, _touchPrevPos, _touchPos;
|
||||
rpl::variable<bool> _touchMaybeSelecting;
|
||||
base::Timer _touchSelectTimer;
|
||||
|
||||
Ui::DraggingScrollManager _selectScroll;
|
||||
|
|
|
@ -25,7 +25,8 @@ void SetupSwipeHandler(
|
|||
not_null<Ui::RpWidget*> widget,
|
||||
not_null<Ui::ScrollArea*> scroll,
|
||||
Fn<void(ChatPaintGestureHorizontalData)> update,
|
||||
Fn<SwipeHandlerFinishData(int)> generateFinishByTop) {
|
||||
Fn<SwipeHandlerFinishData(int)> generateFinishByTop,
|
||||
rpl::producer<bool> dontStart) {
|
||||
constexpr auto kThresholdWidth = 50;
|
||||
const auto threshold = style::ConvertFloatScale(kThresholdWidth);
|
||||
struct State {
|
||||
|
@ -37,6 +38,7 @@ void SetupSwipeHandler(
|
|||
QPointF startAt;
|
||||
QPointF delta;
|
||||
int cursorTop = 0;
|
||||
bool dontStart = false;
|
||||
bool started = false;
|
||||
bool reached = false;
|
||||
bool touch = false;
|
||||
|
@ -44,6 +46,12 @@ void SetupSwipeHandler(
|
|||
rpl::lifetime lifetime;
|
||||
};
|
||||
const auto state = widget->lifetime().make_state<State>();
|
||||
std::move(
|
||||
dontStart
|
||||
) | rpl::start_with_next([=](bool dontStart) {
|
||||
state->dontStart = dontStart;
|
||||
}, state->lifetime);
|
||||
|
||||
const auto updateRatio = [=](float64 ratio) {
|
||||
update({
|
||||
.ratio = std::clamp(ratio, 0., 1.5),
|
||||
|
@ -83,12 +91,15 @@ void SetupSwipeHandler(
|
|||
state->reached = false;
|
||||
};
|
||||
scroll->scrolls() | rpl::start_with_next([=] {
|
||||
processEnd();
|
||||
if (state->orientation != Qt::Vertical) {
|
||||
processEnd();
|
||||
}
|
||||
}, state->lifetime);
|
||||
const auto animationReachCallback = [=] {
|
||||
updateRatio(state->delta.x() / threshold);
|
||||
};
|
||||
struct UpdateArgs {
|
||||
QPoint globalCursor;
|
||||
QPointF position;
|
||||
QPointF delta;
|
||||
bool touch = false;
|
||||
|
@ -99,8 +110,7 @@ void SetupSwipeHandler(
|
|||
state->touch = args.touch;
|
||||
state->startAt = args.position;
|
||||
state->delta = QPointF();
|
||||
state->cursorTop = widget->mapFromGlobal(
|
||||
QCursor::pos()).y();
|
||||
state->cursorTop = widget->mapFromGlobal(args.globalCursor).y();
|
||||
state->finishByTopData = generateFinishByTop(
|
||||
state->cursorTop);
|
||||
if (!state->finishByTopData.callback) {
|
||||
|
@ -112,7 +122,9 @@ void SetupSwipeHandler(
|
|||
- std::abs(args.delta.y());
|
||||
constexpr auto kOrientationThreshold = 1.;
|
||||
if (diffXtoY > kOrientationThreshold) {
|
||||
setOrientation(Qt::Horizontal);
|
||||
if (!state->dontStart) {
|
||||
setOrientation(Qt::Horizontal);
|
||||
}
|
||||
} else if (diffXtoY < -kOrientationThreshold) {
|
||||
setOrientation(Qt::Vertical);
|
||||
} else {
|
||||
|
@ -143,12 +155,12 @@ void SetupSwipeHandler(
|
|||
const auto type = e->type();
|
||||
switch (type) {
|
||||
case QEvent::Leave: {
|
||||
if (state->orientation) {
|
||||
if (state->orientation == Qt::Horizontal) {
|
||||
processEnd();
|
||||
}
|
||||
} break;
|
||||
case QEvent::MouseMove: {
|
||||
if (state->orientation) {
|
||||
if (state->orientation == Qt::Horizontal) {
|
||||
const auto m = static_cast<QMouseEvent*>(e.get());
|
||||
if (std::abs(m->pos().y() - state->cursorTop)
|
||||
> QApplication::startDragDistance()) {
|
||||
|
@ -165,6 +177,9 @@ void SetupSwipeHandler(
|
|||
&& (t->device()->type() == base::TouchDevice::TouchScreen);
|
||||
if (!Platform::IsMac() && !touchscreen) {
|
||||
break;
|
||||
} else if (type == QEvent::TouchBegin) {
|
||||
// Reset state in case we lost some TouchEnd.
|
||||
processEnd();
|
||||
}
|
||||
const auto &touches = t->touchPoints();
|
||||
const auto released = [&](int index) {
|
||||
|
@ -184,6 +199,9 @@ void SetupSwipeHandler(
|
|||
: (state->startAt - touches[0].pos()));
|
||||
} else {
|
||||
updateWith({
|
||||
.globalCursor = (touchscreen
|
||||
? touches[0].screenPos().toPoint()
|
||||
: QCursor::pos()),
|
||||
.position = touches[0].pos(),
|
||||
.delta = state->startAt - touches[0].pos(),
|
||||
.touch = true,
|
||||
|
@ -198,6 +216,9 @@ void SetupSwipeHandler(
|
|||
const auto phase = w->phase();
|
||||
if (Platform::IsMac() || phase == Qt::NoScrollPhase) {
|
||||
break;
|
||||
} else if (phase == Qt::ScrollBegin) {
|
||||
// Reset state in case we lost some TouchEnd.
|
||||
processEnd();
|
||||
}
|
||||
const auto cancel = w->buttons()
|
||||
|| (phase == Qt::ScrollEnd)
|
||||
|
@ -206,6 +227,7 @@ void SetupSwipeHandler(
|
|||
processEnd();
|
||||
} else {
|
||||
updateWith({
|
||||
.globalCursor = w->globalPos(),
|
||||
.position = QPointF(),
|
||||
.delta = state->delta - Ui::ScrollDelta(w),
|
||||
.touch = false,
|
||||
|
|
|
@ -25,6 +25,7 @@ void SetupSwipeHandler(
|
|||
not_null<Ui::RpWidget*> widget,
|
||||
not_null<Ui::ScrollArea*> scroll,
|
||||
Fn<void(ChatPaintGestureHorizontalData)> update,
|
||||
Fn<SwipeHandlerFinishData(int)> generateFinishByTop);
|
||||
Fn<SwipeHandlerFinishData(int)> generateFinishByTop,
|
||||
rpl::producer<bool> dontStart = nullptr);
|
||||
|
||||
} // namespace HistoryView
|
||||
|
|
|
@ -2940,6 +2940,7 @@ void ListWidget::touchEvent(QTouchEvent *e) {
|
|||
_touchSelectTimer.cancel();
|
||||
_touchScroll = _touchSelect = false;
|
||||
_touchScrollState = Ui::TouchScrollState::Manual;
|
||||
_touchMaybeSelecting = false;
|
||||
mouseActionCancel();
|
||||
return;
|
||||
}
|
||||
|
@ -2960,6 +2961,7 @@ void ListWidget::touchEvent(QTouchEvent *e) {
|
|||
|
||||
_touchInProgress = true;
|
||||
if (_touchScrollState == Ui::TouchScrollState::Auto) {
|
||||
_touchMaybeSelecting = false;
|
||||
_touchScrollState = Ui::TouchScrollState::Acceleration;
|
||||
_touchWaitingAcceleration = true;
|
||||
_touchAccelerationTime = crl::now();
|
||||
|
@ -2967,6 +2969,7 @@ void ListWidget::touchEvent(QTouchEvent *e) {
|
|||
_touchStart = _touchPos;
|
||||
} else {
|
||||
_touchScroll = false;
|
||||
_touchMaybeSelecting = true;
|
||||
_touchSelectTimer.callOnce(QApplication::startDragTime());
|
||||
}
|
||||
_touchSelect = false;
|
||||
|
@ -2979,6 +2982,7 @@ void ListWidget::touchEvent(QTouchEvent *e) {
|
|||
mouseActionUpdate(_touchPos);
|
||||
} else if (!_touchScroll && (_touchPos - _touchStart).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
_touchSelectTimer.cancel();
|
||||
_touchMaybeSelecting = false;
|
||||
_touchScroll = true;
|
||||
touchUpdateSpeed();
|
||||
}
|
||||
|
@ -2996,13 +3000,22 @@ void ListWidget::touchEvent(QTouchEvent *e) {
|
|||
} break;
|
||||
|
||||
case QEvent::TouchEnd: {
|
||||
if (!_touchInProgress) return;
|
||||
if (!_touchInProgress) {
|
||||
return;
|
||||
}
|
||||
_touchInProgress = false;
|
||||
auto weak = Ui::MakeWeak(this);
|
||||
const auto notMoved = (_touchPos - _touchStart).manhattanLength()
|
||||
< QApplication::startDragDistance();
|
||||
if (_touchSelect) {
|
||||
mouseActionFinish(_touchPos, Qt::RightButton);
|
||||
QContextMenuEvent contextMenu(QContextMenuEvent::Mouse, mapFromGlobal(_touchPos), _touchPos);
|
||||
showContextMenu(&contextMenu, true);
|
||||
if (notMoved || _touchMaybeSelecting.current()) {
|
||||
mouseActionFinish(_touchPos, Qt::RightButton);
|
||||
auto contextMenu = QContextMenuEvent(
|
||||
QContextMenuEvent::Mouse,
|
||||
mapFromGlobal(_touchPos),
|
||||
_touchPos);
|
||||
showContextMenu(&contextMenu, true);
|
||||
}
|
||||
_touchScroll = false;
|
||||
} else if (_touchScroll) {
|
||||
if (_touchScrollState == Ui::TouchScrollState::Manual) {
|
||||
|
@ -3019,12 +3032,13 @@ void ListWidget::touchEvent(QTouchEvent *e) {
|
|||
_touchWaitingAcceleration = false;
|
||||
_touchPrevPosValid = false;
|
||||
}
|
||||
} else { // One short tap is like left mouse click.
|
||||
} else if (notMoved) { // One short tap is like left mouse click.
|
||||
mouseActionStart(_touchPos, Qt::LeftButton);
|
||||
mouseActionFinish(_touchPos, Qt::LeftButton);
|
||||
}
|
||||
if (weak) {
|
||||
_touchSelectTimer.cancel();
|
||||
_touchMaybeSelecting = false;
|
||||
_touchSelect = false;
|
||||
}
|
||||
} break;
|
||||
|
@ -3064,6 +3078,10 @@ void ListWidget::touchScrollUpdated(const QPoint &screenPos) {
|
|||
touchUpdateSpeed();
|
||||
}
|
||||
|
||||
rpl::producer<bool> ListWidget::touchMaybeSelectingValue() const {
|
||||
return _touchMaybeSelecting.value();
|
||||
}
|
||||
|
||||
void ListWidget::enterEventHook(QEnterEvent *e) {
|
||||
mouseActionUpdate(QCursor::pos());
|
||||
return TWidget::enterEventHook(e);
|
||||
|
@ -3120,6 +3138,7 @@ void ListWidget::updateDragSelection() {
|
|||
|
||||
void ListWidget::onTouchSelect() {
|
||||
_touchSelect = true;
|
||||
_touchMaybeSelecting = true;
|
||||
mouseActionStart(_touchPos, Qt::LeftButton);
|
||||
}
|
||||
|
||||
|
|
|
@ -327,6 +327,7 @@ public:
|
|||
void selectItemAsGroup(not_null<HistoryItem*> item);
|
||||
|
||||
void touchScrollUpdated(const QPoint &screenPos);
|
||||
[[nodiscard]] rpl::producer<bool> touchMaybeSelectingValue() const;
|
||||
|
||||
[[nodiscard]] bool loadedAtTopKnown() const;
|
||||
[[nodiscard]] bool loadedAtTop() const;
|
||||
|
@ -830,6 +831,7 @@ private:
|
|||
bool _touchSelect = false;
|
||||
bool _touchInProgress = false;
|
||||
QPoint _touchStart, _touchPrevPos, _touchPos;
|
||||
rpl::variable<bool> _touchMaybeSelecting;
|
||||
base::Timer _touchSelectTimer;
|
||||
|
||||
Ui::DraggingScrollManager _selectScroll;
|
||||
|
|
|
@ -923,7 +923,7 @@ void RepliesWidget::setupSwipeReply() {
|
|||
});
|
||||
};
|
||||
return result;
|
||||
});
|
||||
}, _inner->touchMaybeSelectingValue());
|
||||
}
|
||||
|
||||
void RepliesWidget::chooseAttach(
|
||||
|
|
Loading…
Add table
Reference in a new issue