Improve mouse/keyboard selection interactions.

Fixes #5458.
This commit is contained in:
John Preston 2018-12-25 16:41:40 +04:00
parent 44ff8f92ac
commit e5536880fb
9 changed files with 139 additions and 115 deletions

View File

@ -746,6 +746,8 @@ void PeerListContent::clearAllContent() {
setSelected(Selected()); setSelected(Selected());
setPressed(Selected()); setPressed(Selected());
setContexted(Selected()); setContexted(Selected());
_mouseSelection = false;
_lastMousePosition = std::nullopt;
_rowsById.clear(); _rowsById.clear();
_rowsByPeer.clear(); _rowsByPeer.clear();
_filterResults.clear(); _filterResults.clear();
@ -836,7 +838,9 @@ void PeerListContent::refreshRows() {
if (_visibleBottom > 0) { if (_visibleBottom > 0) {
checkScrollForPreload(); checkScrollForPreload();
} }
updateSelection(); if (_mouseSelection) {
selectByMouse(QCursor::pos());
}
update(); update();
} }
@ -943,29 +947,32 @@ void PeerListContent::enterEventHook(QEvent *e) {
} }
void PeerListContent::leaveEventHook(QEvent *e) { void PeerListContent::leaveEventHook(QEvent *e) {
_mouseSelection = false;
setMouseTracking(false); setMouseTracking(false);
setSelected(Selected()); if (_mouseSelection) {
setSelected(Selected());
_mouseSelection = false;
_lastMousePosition = std::nullopt;
}
} }
void PeerListContent::mouseMoveEvent(QMouseEvent *e) { void PeerListContent::mouseMoveEvent(QMouseEvent *e) {
handleMouseMove(e->globalPos()); handleMouseMove(e->globalPos());
} }
void PeerListContent::handleMouseMove(QPoint position) { void PeerListContent::handleMouseMove(QPoint globalPosition) {
if (_mouseSelection || _lastMousePosition != position) { if (!_lastMousePosition) {
_lastMousePosition = position; _lastMousePosition = globalPosition;
_mouseSelection = true; return;
updateSelection(); } else if (!_mouseSelection
&& *_lastMousePosition == globalPosition) {
return;
} }
selectByMouse(globalPosition);
} }
void PeerListContent::mousePressEvent(QMouseEvent *e) { void PeerListContent::mousePressEvent(QMouseEvent *e) {
_pressButton = e->button(); _pressButton = e->button();
_mouseSelection = true; selectByMouse(e->globalPos());
_lastMousePosition = e->globalPos();
updateSelection();
setPressed(_selected); setPressed(_selected);
if (auto row = getRow(_selected.index)) { if (auto row = getRow(_selected.index)) {
auto updateCallback = [this, row, hint = _selected.index] { auto updateCallback = [this, row, hint = _selected.index] {
@ -1157,6 +1164,7 @@ void PeerListContent::selectSkip(int direction) {
return; return;
} }
_mouseSelection = false; _mouseSelection = false;
_lastMousePosition = std::nullopt;
auto newSelectedIndex = _selected.index.value + direction; auto newSelectedIndex = _selected.index.value + direction;
@ -1305,7 +1313,6 @@ void PeerListContent::searchQueryChanged(QString query) {
_controller->search(_searchQuery); _controller->search(_searchQuery);
} }
refreshRows(); refreshRows();
restoreSelection();
} }
} }
@ -1357,6 +1364,8 @@ void PeerListContent::setSearchQuery(
setSelected(Selected()); setSelected(Selected());
setPressed(Selected()); setPressed(Selected());
setContexted(Selected()); setContexted(Selected());
_mouseSelection = false;
_lastMousePosition = std::nullopt;
_searchQuery = query; _searchQuery = query;
_normalizedSearchQuery = normalizedQuery; _normalizedSearchQuery = normalizedQuery;
_mentionHighlight = _searchQuery.startsWith('@') _mentionHighlight = _searchQuery.startsWith('@')
@ -1403,8 +1412,9 @@ void PeerListContent::setContexted(Selected contexted) {
} }
void PeerListContent::restoreSelection() { void PeerListContent::restoreSelection() {
_lastMousePosition = QCursor::pos(); if (_mouseSelection) {
updateSelection(); selectByMouse(QCursor::pos());
}
} }
auto PeerListContent::saveSelectedData(Selected from) auto PeerListContent::saveSelectedData(Selected from)
@ -1426,11 +1436,11 @@ auto PeerListContent::restoreSelectedData(SelectedSaved from)
return result; return result;
} }
void PeerListContent::updateSelection() { void PeerListContent::selectByMouse(QPoint globalPosition) {
if (!_mouseSelection) return; _mouseSelection = true;
_lastMousePosition = globalPosition;
auto point = mapFromGlobal(_lastMousePosition); const auto point = mapFromGlobal(globalPosition);
auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(_lastMousePosition)); auto in = parentWidget()->rect().contains(parentWidget()->mapFromGlobal(globalPosition));
auto selected = Selected(); auto selected = Selected();
auto rowsPointY = point.y() - rowsTop(); auto rowsPointY = point.y() - rowsTop();
selected.index.value = (in && rowsPointY >= 0 && rowsPointY < shownRowsCount() * _rowHeight) ? (rowsPointY / _rowHeight) : -1; selected.index.value = (in && rowsPointY >= 0 && rowsPointY < shownRowsCount() * _rowHeight) ? (rowsPointY / _rowHeight) : -1;

View File

@ -553,7 +553,7 @@ private:
SelectedSaved saveSelectedData(Selected from); SelectedSaved saveSelectedData(Selected from);
Selected restoreSelectedData(SelectedSaved from); Selected restoreSelectedData(SelectedSaved from);
void updateSelection(); void selectByMouse(QPoint globalPosition);
void loadProfilePhotos(); void loadProfilePhotos();
void checkScrollForPreload(); void checkScrollForPreload();
@ -587,7 +587,7 @@ private:
void clearSearchRows(); void clearSearchRows();
void clearAllContent(); void clearAllContent();
void handleMouseMove(QPoint position); void handleMouseMove(QPoint globalPosition);
void mousePressReleased(Qt::MouseButton button); void mousePressReleased(Qt::MouseButton button);
const style::PeerList &_st; const style::PeerList &_st;
@ -602,6 +602,7 @@ private:
Selected _pressed; Selected _pressed;
Selected _contexted; Selected _contexted;
bool _mouseSelection = false; bool _mouseSelection = false;
std::optional<QPoint> _lastMousePosition;
Qt::MouseButton _pressButton = Qt::LeftButton; Qt::MouseButton _pressButton = Qt::LeftButton;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests; rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
@ -622,8 +623,6 @@ private:
object_ptr<Ui::FlatLabel> _searchNoResults = { nullptr }; object_ptr<Ui::FlatLabel> _searchNoResults = { nullptr };
object_ptr<Ui::FlatLabel> _searchLoading = { nullptr }; object_ptr<Ui::FlatLabel> _searchLoading = { nullptr };
QPoint _lastMousePosition;
std::vector<std::unique_ptr<PeerListRow>> _searchRows; std::vector<std::unique_ptr<PeerListRow>> _searchRows;
base::Timer _repaintByStatus; base::Timer _repaintByStatus;
base::unique_qptr<Ui::PopupMenu> _contextMenu; base::unique_qptr<Ui::PopupMenu> _contextMenu;

View File

@ -241,6 +241,7 @@ void SuggestionsWidget::handleKeyEvent(int key) {
} }
_mouseSelection = false; _mouseSelection = false;
_lastMousePosition = std::nullopt;
setSelected(newSelected); setSelected(newSelected);
} }
@ -272,6 +273,7 @@ void SuggestionsWidget::clearMouseSelection() {
void SuggestionsWidget::clearSelection() { void SuggestionsWidget::clearSelection() {
_mouseSelection = false; _mouseSelection = false;
_lastMousePosition = std::nullopt;
setSelected(-1); setSelected(-1);
} }
@ -296,24 +298,30 @@ void SuggestionsWidget::mouseMoveEvent(QMouseEvent *e) {
auto inner = rect().marginsRemoved(QMargins(0, _st->skip, 0, _st->skip)); auto inner = rect().marginsRemoved(QMargins(0, _st->skip, 0, _st->skip));
auto localPosition = e->pos(); auto localPosition = e->pos();
if (inner.contains(localPosition)) { if (inner.contains(localPosition)) {
_mouseSelection = true; const auto globalPosition = e->globalPos();
updateSelection(e->globalPos()); if (!_lastMousePosition) {
_lastMousePosition = globalPosition;
return;
} else if (!_mouseSelection
&& *_lastMousePosition == globalPosition) {
return;
}
selectByMouse(globalPosition);
} else { } else {
clearMouseSelection(); clearMouseSelection();
} }
} }
void SuggestionsWidget::updateSelection(QPoint globalPosition) { void SuggestionsWidget::selectByMouse(QPoint globalPosition) {
if (!_mouseSelection) return; _mouseSelection = true;
_lastMousePosition = globalPosition;
auto p = mapFromGlobal(globalPosition) - QPoint(0, _st->skip); auto p = mapFromGlobal(globalPosition) - QPoint(0, _st->skip);
auto selected = (p.y() >= 0) ? (p.y() / _rowHeight) : -1; auto selected = (p.y() >= 0) ? (p.y() / _rowHeight) : -1;
setSelected((selected >= 0 && selected < _rows.size()) ? selected : -1); setSelected((selected >= 0 && selected < _rows.size()) ? selected : -1);
} }
void SuggestionsWidget::mousePressEvent(QMouseEvent *e) { void SuggestionsWidget::mousePressEvent(QMouseEvent *e) {
if (!_mouseSelection) { selectByMouse(e->globalPos());
return;
}
if (_selected >= 0 && _selected < _rows.size()) { if (_selected >= 0 && _selected < _rows.size()) {
setPressed(_selected); setPressed(_selected);
if (!_rows[_pressed].ripple()) { if (!_rows[_pressed].ripple()) {

View File

@ -49,7 +49,7 @@ private:
void updateSelectedItem(); void updateSelectedItem();
int itemTop(int index); int itemTop(int index);
void updateItem(int index); void updateItem(int index);
void updateSelection(QPoint globalPosition); void selectByMouse(QPoint globalPosition);
void triggerSelectedRow(); void triggerSelectedRow();
void triggerRow(const Row &row); void triggerRow(const Row &row);
@ -59,6 +59,7 @@ private:
std::vector<Row> _rows; std::vector<Row> _rows;
int _rowHeight = 0; int _rowHeight = 0;
std::optional<QPoint> _lastMousePosition;
bool _mouseSelection = false; bool _mouseSelection = false;
int _selected = -1; int _selected = -1;
int _pressed = -1; int _pressed = -1;

View File

@ -682,13 +682,21 @@ void FieldAutocompleteInner::resizeEvent(QResizeEvent *e) {
} }
void FieldAutocompleteInner::mouseMoveEvent(QMouseEvent *e) { void FieldAutocompleteInner::mouseMoveEvent(QMouseEvent *e) {
_mousePos = mapToGlobal(e->pos()); const auto globalPosition = e->globalPos();
_mouseSel = true; if (!_lastMousePosition) {
onUpdateSelected(true); _lastMousePosition = globalPosition;
return;
} else if (!_mouseSelection
&& *_lastMousePosition == globalPosition) {
return;
}
selectByMouse(globalPosition);
} }
void FieldAutocompleteInner::clearSel(bool hidden) { void FieldAutocompleteInner::clearSel(bool hidden) {
_mouseSel = _overDelete = false; _overDelete = false;
_mouseSelection = false;
_lastMousePosition = std::nullopt;
setSel((_mrows->isEmpty() && _brows->isEmpty() && _hrows->isEmpty()) ? -1 : 0); setSel((_mrows->isEmpty() && _brows->isEmpty() && _hrows->isEmpty()) ? -1 : 0);
if (hidden) { if (hidden) {
_down = -1; _down = -1;
@ -697,7 +705,9 @@ void FieldAutocompleteInner::clearSel(bool hidden) {
} }
bool FieldAutocompleteInner::moveSel(int key) { bool FieldAutocompleteInner::moveSel(int key) {
_mouseSel = false; _mouseSelection = false;
_lastMousePosition = std::nullopt;
int32 maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? (_brows->isEmpty() ? _srows->size() : _brows->size()) : _hrows->size()) : _mrows->size()); int32 maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? (_brows->isEmpty() ? _srows->size() : _brows->size()) : _hrows->size()) : _mrows->size());
int32 direction = (key == Qt::Key_Up) ? -1 : (key == Qt::Key_Down ? 1 : 0); int32 direction = (key == Qt::Key_Up) ? -1 : (key == Qt::Key_Down ? 1 : 0);
if (!_srows->empty()) { if (!_srows->empty()) {
@ -760,12 +770,9 @@ void FieldAutocompleteInner::setRecentInlineBotsInRows(int32 bots) {
} }
void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) { void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
_mousePos = mapToGlobal(e->pos()); selectByMouse(e->globalPos());
_mouseSel = true;
onUpdateSelected(true);
if (e->button() == Qt::LeftButton) { if (e->button() == Qt::LeftButton) {
if (_overDelete && _sel >= 0 && _sel < (_mrows->isEmpty() ? _hrows->size() : _recentInlineBotsInRows)) { if (_overDelete && _sel >= 0 && _sel < (_mrows->isEmpty() ? _hrows->size() : _recentInlineBotsInRows)) {
_mousePos = mapToGlobal(e->pos());
bool removed = false; bool removed = false;
if (_mrows->isEmpty()) { if (_mrows->isEmpty()) {
QString toRemove = _hrows->at(_sel); QString toRemove = _hrows->at(_sel);
@ -792,8 +799,7 @@ void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
} }
_parent->updateFiltered(); _parent->updateFiltered();
_mouseSel = true; selectByMouse(e->globalPos());
onUpdateSelected(true);
} else if (_srows->empty()) { } else if (_srows->empty()) {
chooseSelected(FieldAutocomplete::ChooseMethod::ByClick); chooseSelected(FieldAutocomplete::ChooseMethod::ByClick);
} else { } else {
@ -809,9 +815,7 @@ void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) {
int32 pressed = _down; int32 pressed = _down;
_down = -1; _down = -1;
_mousePos = mapToGlobal(e->pos()); selectByMouse(e->globalPos());
_mouseSel = true;
onUpdateSelected(true);
if (_previewShown) { if (_previewShown) {
_previewShown = false; _previewShown = false;
@ -825,14 +829,14 @@ void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) {
void FieldAutocompleteInner::enterEventHook(QEvent *e) { void FieldAutocompleteInner::enterEventHook(QEvent *e) {
setMouseTracking(true); setMouseTracking(true);
_mousePos = QCursor::pos();
onUpdateSelected(true);
} }
void FieldAutocompleteInner::leaveEventHook(QEvent *e) { void FieldAutocompleteInner::leaveEventHook(QEvent *e) {
setMouseTracking(false); setMouseTracking(false);
if (_sel >= 0) { if (_mouseSelection) {
setSel(-1); setSel(-1);
_mouseSelection = false;
_lastMousePosition = std::nullopt;
} }
} }
@ -862,11 +866,14 @@ void FieldAutocompleteInner::setSel(int sel, bool scroll) {
} }
} }
void FieldAutocompleteInner::onUpdateSelected(bool force) { void FieldAutocompleteInner::selectByMouse(QPoint globalPosition) {
QPoint mouse(mapFromGlobal(_mousePos)); _mouseSelection = true;
if ((!force && !rect().contains(mouse)) || !_mouseSel) return; _lastMousePosition = globalPosition;
const auto mouse = mapFromGlobal(globalPosition);
if (_down >= 0 && !_previewShown) return; if (_down >= 0 && !_previewShown) {
return;
}
int32 sel = -1, maxSel = 0; int32 sel = -1, maxSel = 0;
if (!_srows->empty()) { if (!_srows->empty()) {
@ -900,10 +907,12 @@ void FieldAutocompleteInner::onUpdateSelected(bool force) {
} }
void FieldAutocompleteInner::onParentGeometryChanged() { void FieldAutocompleteInner::onParentGeometryChanged() {
_mousePos = QCursor::pos(); const auto globalPosition = QCursor::pos();
if (rect().contains(mapFromGlobal(_mousePos))) { if (rect().contains(mapFromGlobal(globalPosition))) {
setMouseTracking(true); setMouseTracking(true);
onUpdateSelected(true); if (_mouseSelection) {
selectByMouse(globalPosition);
}
} }
} }

View File

@ -152,7 +152,6 @@ signals:
public slots: public slots:
void onParentGeometryChanged(); void onParentGeometryChanged();
void onUpdateSelected(bool force = false);
private: private:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
@ -168,6 +167,7 @@ private:
void updateSelectedRow(); void updateSelectedRow();
void setSel(int sel, bool scroll = false); void setSel(int sel, bool scroll = false);
void showPreview(); void showPreview();
void selectByMouse(QPoint global);
FieldAutocomplete *_parent = nullptr; FieldAutocomplete *_parent = nullptr;
MentionRows *_mrows = nullptr; MentionRows *_mrows = nullptr;
@ -178,8 +178,8 @@ private:
int _recentInlineBotsInRows = 0; int _recentInlineBotsInRows = 0;
int _sel = -1; int _sel = -1;
int _down = -1; int _down = -1;
bool _mouseSel = false; std::optional<QPoint> _lastMousePosition;
QPoint _mousePos; bool _mouseSelection = false;
bool _overDelete = false; bool _overDelete = false;

View File

@ -692,11 +692,15 @@ void DialogsInner::activate() {
} }
void DialogsInner::mouseMoveEvent(QMouseEvent *e) { void DialogsInner::mouseMoveEvent(QMouseEvent *e) {
if (_mouseLastGlobalPosition != e->globalPos()) { const auto globalPosition = e->globalPos();
_mouseLastGlobalPosition = e->globalPos(); if (!_lastMousePosition) {
_mouseSelection = true; _lastMousePosition = globalPosition;
return;
} else if (!_mouseSelection
&& *_lastMousePosition == globalPosition) {
return;
} }
updateSelected(e->pos()); selectByMouse(globalPosition);
} }
void DialogsInner::clearIrrelevantState() { void DialogsInner::clearIrrelevantState() {
@ -718,16 +722,15 @@ void DialogsInner::clearIrrelevantState() {
} }
} }
void DialogsInner::updateSelected(QPoint localPos) { void DialogsInner::selectByMouse(QPoint globalPosition) {
if (updateReorderPinned(localPos)) { const auto local = mapFromGlobal(globalPosition);
if (updateReorderPinned(local)) {
return; return;
} }
_mouseSelection = true;
_lastMousePosition = globalPosition;
if (!_mouseSelection) { int w = width(), mouseY = local.y();
return;
}
int w = width(), mouseY = localPos.y();
clearIrrelevantState(); clearIrrelevantState();
if (_state == State::Default) { if (_state == State::Default) {
auto importantSwitchSelected = (_dialogsImportant && mouseY >= 0 && mouseY < dialogsOffset()); auto importantSwitchSelected = (_dialogsImportant && mouseY >= 0 && mouseY < dialogsOffset());
@ -756,7 +759,7 @@ void DialogsInner::updateSelected(QPoint localPos) {
_hashtagSelected = hashtagSelected; _hashtagSelected = hashtagSelected;
updateSelectedRow(); updateSelectedRow();
} }
_hashtagDeleteSelected = (_hashtagSelected >= 0) && (localPos.x() >= w - st::mentionHeight); _hashtagDeleteSelected = (_hashtagSelected >= 0) && (local.x() >= w - st::mentionHeight);
} }
if (!_filterResults.isEmpty()) { if (!_filterResults.isEmpty()) {
auto skip = filteredOffset(); auto skip = filteredOffset();
@ -801,8 +804,7 @@ void DialogsInner::updateSelected(QPoint localPos) {
} }
void DialogsInner::mousePressEvent(QMouseEvent *e) { void DialogsInner::mousePressEvent(QMouseEvent *e) {
_mouseSelection = true; selectByMouse(e->globalPos());
updateSelected(e->pos());
_pressButton = e->button(); _pressButton = e->button();
setPressed(_selected); setPressed(_selected);
@ -851,7 +853,7 @@ void DialogsInner::mousePressEvent(QMouseEvent *e) {
} }
if (anim::Disabled() if (anim::Disabled()
&& (!_pressed || !_pressed->entry()->isPinnedDialog())) { && (!_pressed || !_pressed->entry()->isPinnedDialog())) {
mousePressReleased(e->button()); mousePressReleased(e->globalPos(), e->button());
} }
} }
@ -1072,15 +1074,16 @@ void DialogsInner::step_pinnedShifting(TimeMs ms, bool timer) {
} }
void DialogsInner::mouseReleaseEvent(QMouseEvent *e) { void DialogsInner::mouseReleaseEvent(QMouseEvent *e) {
mousePressReleased(e->button()); mousePressReleased(e->globalPos(), e->button());
} }
void DialogsInner::mousePressReleased(Qt::MouseButton button) { void DialogsInner::mousePressReleased(
QPoint globalPosition,
Qt::MouseButton button) {
auto wasDragging = (_dragging != nullptr); auto wasDragging = (_dragging != nullptr);
if (wasDragging) { if (wasDragging) {
updateReorderIndexGetCount(); updateReorderIndexGetCount();
if (_draggingIndex >= 0) { if (_draggingIndex >= 0) {
auto localPosition = mapFromGlobal(QCursor::pos());
_pinnedRows[_draggingIndex].yadd.start(0.); _pinnedRows[_draggingIndex].yadd.start(0.);
_pinnedRows[_draggingIndex].animStartTime = getms(); _pinnedRows[_draggingIndex].animStartTime = getms();
if (!_a_pinnedShifting.animating()) { if (!_a_pinnedShifting.animating()) {
@ -1105,7 +1108,7 @@ void DialogsInner::mousePressReleased(Qt::MouseButton button) {
auto searchedPressed = _searchedPressed; auto searchedPressed = _searchedPressed;
setSearchedPressed(-1); setSearchedPressed(-1);
if (wasDragging) { if (wasDragging) {
updateSelected(); selectByMouse(globalPosition);
} }
updateSelectedRow(); updateSelectedRow();
if (!wasDragging && button == Qt::LeftButton) { if (!wasDragging && button == Qt::LeftButton) {
@ -1439,7 +1442,6 @@ void DialogsInner::updateDialogRow(
void DialogsInner::enterEventHook(QEvent *e) { void DialogsInner::enterEventHook(QEvent *e) {
setMouseTracking(true); setMouseTracking(true);
updateSelected();
} }
void DialogsInner::updateSelectedRow(Dialogs::Key key) { void DialogsInner::updateSelectedRow(Dialogs::Key key) {
@ -1498,6 +1500,7 @@ void DialogsInner::dragLeft() {
void DialogsInner::clearSelection() { void DialogsInner::clearSelection() {
_mouseSelection = false; _mouseSelection = false;
_lastMousePosition = std::nullopt;
if (_importantSwitchSelected if (_importantSwitchSelected
|| _selected || _selected
|| _filteredSelected >= 0 || _filteredSelected >= 0
@ -1516,8 +1519,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
_menu = nullptr; _menu = nullptr;
if (e->reason() == QContextMenuEvent::Mouse) { if (e->reason() == QContextMenuEvent::Mouse) {
_mouseSelection = true; selectByMouse(e->globalPos());
updateSelected();
} }
const auto key = [&]() -> Dialogs::Key { const auto key = [&]() -> Dialogs::Key {
@ -1536,7 +1538,7 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
_menuKey = key; _menuKey = key;
if (_pressButton != Qt::LeftButton) { if (_pressButton != Qt::LeftButton) {
mousePressReleased(_pressButton); mousePressReleased(e->globalPos(), _pressButton);
} }
_menu = base::make_unique_q<Ui::PopupMenu>(this); _menu = base::make_unique_q<Ui::PopupMenu>(this);
@ -1561,11 +1563,10 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
if (_menuKey) { if (_menuKey) {
updateSelectedRow(base::take(_menuKey)); updateSelectedRow(base::take(_menuKey));
} }
auto localPos = mapFromGlobal(QCursor::pos()); const auto globalPosition = QCursor::pos();
if (rect().contains(localPos)) { if (rect().contains(mapFromGlobal(globalPosition))) {
_mouseSelection = true;
setMouseTracking(true); setMouseTracking(true);
updateSelected(localPos); selectByMouse(globalPosition);
} }
}); });
_menu->popup(e->globalPos()); _menu->popup(e->globalPos());
@ -1573,10 +1574,12 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
} }
void DialogsInner::onParentGeometryChanged() { void DialogsInner::onParentGeometryChanged() {
auto localPos = mapFromGlobal(QCursor::pos()); const auto globalPosition = QCursor::pos();
if (rect().contains(localPos)) { if (rect().contains(mapFromGlobal(globalPosition))) {
setMouseTracking(true); setMouseTracking(true);
updateSelected(localPos); if (_mouseSelection) {
selectByMouse(globalPosition);
}
} }
} }
@ -1684,7 +1687,7 @@ void DialogsInner::onFilterUpdate(QString newFilter, bool force) {
} }
refresh(true); refresh(true);
} }
setMouseSelection(false, true); clearMouseSelection(true);
} }
if (_state != State::Default) { if (_state != State::Default) {
emit searchMessages(); emit searchMessages();
@ -1697,7 +1700,7 @@ void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) {
if (!_hashtagResults.empty()) { if (!_hashtagResults.empty()) {
_hashtagResults.clear(); _hashtagResults.clear();
refresh(true); refresh(true);
setMouseSelection(false, true); clearMouseSelection(true);
} }
return; return;
} }
@ -1717,7 +1720,7 @@ void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) {
} }
} }
refresh(true); refresh(true);
setMouseSelection(false, true); clearMouseSelection(true);
} }
DialogsInner::~DialogsInner() { DialogsInner::~DialogsInner() {
@ -1733,9 +1736,8 @@ void DialogsInner::clearSearchResults(bool clearPeerSearchResults) {
_lastSearchId = _lastSearchMigratedId = 0; _lastSearchId = _lastSearchMigratedId = 0;
} }
PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) { PeerData *DialogsInner::updateFromParentDrag(QPoint globalPosition) {
_mouseSelection = true; selectByMouse(globalPosition);
updateSelected(mapFromGlobal(globalPos));
const auto getPeerFromRow = [](Dialogs::Row *row) -> PeerData* { const auto getPeerFromRow = [](Dialogs::Row *row) -> PeerData* {
if (const auto history = row ? row->history() : nullptr) { if (const auto history = row ? row->history() : nullptr) {
return history->peer; return history->peer;
@ -2106,9 +2108,10 @@ void DialogsInner::refresh(bool toTop) {
update(); update();
} }
void DialogsInner::setMouseSelection(bool mouseSelection, bool toTop) { void DialogsInner::clearMouseSelection(bool clearSelection) {
_mouseSelection = mouseSelection; _mouseSelection = false;
if (!_mouseSelection && toTop) { _lastMousePosition = std::nullopt;
if (clearSelection) {
if (_state == State::Default) { if (_state == State::Default) {
_selected = nullptr; _selected = nullptr;
_importantSwitchSelected = false; _importantSwitchSelected = false;
@ -2215,6 +2218,7 @@ void DialogsInner::clearFilter() {
} }
void DialogsInner::selectSkip(int32 direction) { void DialogsInner::selectSkip(int32 direction) {
clearMouseSelection();
if (_state == State::Default) { if (_state == State::Default) {
if (_importantSwitchSelected) { if (_importantSwitchSelected) {
if (!shownDialogs()->isEmpty() && direction > 0) { if (!shownDialogs()->isEmpty() && direction > 0) {
@ -2330,6 +2334,7 @@ void DialogsInner::scrollToEntry(const Dialogs::RowDescriptor &entry) {
} }
void DialogsInner::selectSkipPage(int32 pixels, int32 direction) { void DialogsInner::selectSkipPage(int32 pixels, int32 direction) {
clearMouseSelection();
int toSkip = pixels / int(st::dialogsRowHeight); int toSkip = pixels / int(st::dialogsRowHeight);
if (_state == State::Default) { if (_state == State::Default) {
if (!_selected) { if (!_selected) {
@ -2457,9 +2462,7 @@ bool DialogsInner::chooseHashtag() {
cSetRecentSearchHashtags(recent); cSetRecentSearchHashtags(recent);
Local::writeRecentHashtagsAndBots(); Local::writeRecentHashtagsAndBots();
emit refreshHashtags(); emit refreshHashtags();
selectByMouse(QCursor::pos());
_mouseSelection = true;
updateSelected();
} else { } else {
Local::saveRecentSearchHashtags('#' + hashtag->tag); Local::saveRecentSearchHashtags('#' + hashtag->tag);
emit completeHashtag(hashtag->tag); emit completeHashtag(hashtag->tag);
@ -2534,6 +2537,8 @@ bool DialogsInner::chooseRow() {
emit clearSearchQuery(); emit clearSearchQuery();
} }
updateSelectedRow(); updateSelectedRow();
_mouseSelection = false;
_lastMousePosition = std::nullopt;
_selected = nullptr; _selected = nullptr;
_hashtagSelected _hashtagSelected
= _filteredSelected = _filteredSelected

View File

@ -76,8 +76,6 @@ public:
MsgId lastSearchId() const; MsgId lastSearchId() const;
MsgId lastSearchMigratedId() const; MsgId lastSearchMigratedId() const;
void setMouseSelection(bool mouseSelection, bool toTop = false);
enum class State { enum class State {
Default, Default,
Filtered, Filtered,
@ -93,7 +91,7 @@ public:
void onFilterUpdate(QString newFilter, bool force = false); void onFilterUpdate(QString newFilter, bool force = false);
void onHashtagFilterUpdate(QStringRef newFilter); void onHashtagFilterUpdate(QStringRef newFilter);
PeerData *updateFromParentDrag(QPoint globalPos); PeerData *updateFromParentDrag(QPoint globalPosition);
void setLoadMoreCallback(Fn<void()> callback) { void setLoadMoreCallback(Fn<void()> callback) {
_loadMoreCallback = std::move(callback); _loadMoreCallback = std::move(callback);
@ -154,13 +152,11 @@ private:
not_null<Dialogs::FakeRow*> result, not_null<Dialogs::FakeRow*> result,
const Dialogs::RowDescriptor &entry) const; const Dialogs::RowDescriptor &entry) const;
void clearMouseSelection(bool clearSelection = false);
void userIsContactUpdated(not_null<UserData*> user); void userIsContactUpdated(not_null<UserData*> user);
void mousePressReleased(Qt::MouseButton button); void mousePressReleased(QPoint globalPosition, Qt::MouseButton button);
void clearIrrelevantState(); void clearIrrelevantState();
void updateSelected() { void selectByMouse(QPoint globalPosition);
updateSelected(mapFromGlobal(QCursor::pos()));
}
void updateSelected(QPoint localPos);
void loadPeerPhotos(); void loadPeerPhotos();
void setImportantSwitchPressed(bool pressed); void setImportantSwitchPressed(bool pressed);
void setPressed(Dialogs::Row *pressed); void setPressed(Dialogs::Row *pressed);
@ -296,7 +292,7 @@ private:
DialogsList _contacts; DialogsList _contacts;
bool _mouseSelection = false; bool _mouseSelection = false;
QPoint _mouseLastGlobalPosition; std::optional<QPoint> _lastMousePosition;
Qt::MouseButton _pressButton = Qt::LeftButton; Qt::MouseButton _pressButton = Qt::LeftButton;
std::unique_ptr<ImportantSwitch> _importantSwitch; std::unique_ptr<ImportantSwitch> _importantSwitch;

View File

@ -1378,16 +1378,12 @@ void DialogsWidget::keyPressEvent(QKeyEvent *e) {
} }
} }
} else if (e->key() == Qt::Key_Down) { } else if (e->key() == Qt::Key_Down) {
_inner->setMouseSelection(false);
_inner->selectSkip(1); _inner->selectSkip(1);
} else if (e->key() == Qt::Key_Up) { } else if (e->key() == Qt::Key_Up) {
_inner->setMouseSelection(false);
_inner->selectSkip(-1); _inner->selectSkip(-1);
} else if (e->key() == Qt::Key_PageDown) { } else if (e->key() == Qt::Key_PageDown) {
_inner->setMouseSelection(false);
_inner->selectSkipPage(_scroll->height(), 1); _inner->selectSkipPage(_scroll->height(), 1);
} else if (e->key() == Qt::Key_PageUp) { } else if (e->key() == Qt::Key_PageUp) {
_inner->setMouseSelection(false);
_inner->selectSkipPage(_scroll->height(), -1); _inner->selectSkipPage(_scroll->height(), -1);
} else { } else {
e->ignore(); e->ignore();