From 00919f32320cbbba96087367a41e1257604f8dcc Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 26 Aug 2025 14:19:36 +0400 Subject: [PATCH] Support arrows in chat switch. --- Telegram/SourceFiles/core/application.cpp | 2 + Telegram/SourceFiles/core/shortcuts.cpp | 38 +++++++---- .../window/window_chat_switch_process.cpp | 67 ++++++++++++++----- .../window/window_chat_switch_process.h | 3 + 4 files changed, 81 insertions(+), 29 deletions(-) diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 190f4431b4..933e248d05 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -648,6 +648,8 @@ bool Application::eventFilter(QObject *object, QEvent *e) { if (base::Platform::GlobalShortcuts::IsToggleFullScreenKey(event) && toggleActiveWindowFullScreen()) { return true; + } else if (Shortcuts::HandlePossibleChatSwitch(event)) { + return true; } } break; case QEvent::MouseButtonPress: diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp index 34d5457f10..9f4c053146 100644 --- a/Telegram/SourceFiles/core/shortcuts.cpp +++ b/Telegram/SourceFiles/core/shortcuts.cpp @@ -805,12 +805,22 @@ bool HandleEvent( return Launch(Data.lookup(object)); } -void CancelChatSwitch(Qt::Key result) { +bool CancelChatSwitch(Qt::Key result) { ChatSwitchModifier = Qt::Key(); - if (ChatSwitchStarted) { - ChatSwitchStarted = false; - ChatSwitchStream.fire({ .action = result }); + if (!ChatSwitchStarted) { + return false; } + ChatSwitchStarted = false; + ChatSwitchStream.fire({ .action = result }); + return true; +} + +bool NavigateChatSwitch(Qt::Key result) { + if (!ChatSwitchStarted) { + return false; + } + ChatSwitchStream.fire({ .action = result }); + return true; } rpl::producer ChatSwitchRequests() { @@ -823,17 +833,9 @@ bool HandlePossibleChatSwitch(not_null event) { return false; } else if (type == QEvent::ShortcutOverride) { const auto key = Qt::Key(event->key()); - if (key == Qt::Key_Escape) { - CancelChatSwitch(Qt::Key_Escape); - return false; - } else if (key == Qt::Key_Return || key == Qt::Key_Enter) { - CancelChatSwitch(Qt::Key_Enter); - return false; - } const auto ctrl = Platform::IsMac() ? Qt::MetaModifier : Qt::ControlModifier; - if (Data.handles(QKeySequence(ctrl | Qt::Key_Tab)) && (Data.handles(ctrl | Qt::ShiftModifier | Qt::Key_Backtab) || Data.handles(ctrl | Qt::ShiftModifier | Qt::Key_Tab) @@ -872,6 +874,18 @@ bool HandlePossibleChatSwitch(not_null event) { return true; } } + } else if (type == QEvent::KeyPress) { + const auto key = Qt::Key(event->key()); + if (key == Qt::Key_Escape) { + return CancelChatSwitch(Qt::Key_Escape); + } else if (key == Qt::Key_Return || key == Qt::Key_Enter) { + return CancelChatSwitch(Qt::Key_Enter); + } else if (key == Qt::Key_Left + || key == Qt::Key_Right + || key == Qt::Key_Up + || key == Qt::Key_Down) { + return NavigateChatSwitch(key); + } } else if (type == QEvent::KeyRelease) { const auto key = Qt::Key(event->key()); if (key == ChatSwitchModifier) { diff --git a/Telegram/SourceFiles/window/window_chat_switch_process.cpp b/Telegram/SourceFiles/window/window_chat_switch_process.cpp index c856a98ac7..871c54a97c 100644 --- a/Telegram/SourceFiles/window/window_chat_switch_process.cpp +++ b/Telegram/SourceFiles/window/window_chat_switch_process.cpp @@ -210,9 +210,8 @@ rpl::producer<> ChatSwitchProcess::closeRequests() const { } void ChatSwitchProcess::process(const Request &request) { - Expects(_selected < int(_list.size())); + Expects(_selected < _shownCount); - const auto count = int(_list.size()); if (request.action == Qt::Key_Escape) { _closeRequests.fire({}); } else if (request.action == Qt::Key_Enter) { @@ -221,18 +220,28 @@ void ChatSwitchProcess::process(const Request &request) { } else { _closeRequests.fire({}); } - } else if (request.action == Qt::Key_Tab) { - if (_selected < 0 || _selected + 1 >= count) { + } else if (request.action == Qt::Key_Tab + || request.action == Qt::Key_Right) { + if (_selected < 0 || _selected + 1 >= _shownCount) { setSelected(0); } else { setSelected(_selected + 1); } - } else if (request.action == Qt::Key_Backtab) { + } else if (request.action == Qt::Key_Backtab + || request.action == Qt::Key_Left) { if (_selected <= 0) { - setSelected(count - 1); + setSelected(_shownCount - 1); } else { setSelected(_selected - 1); } + } else if (request.action == Qt::Key_Up) { + const auto now = std::max(_selected, 0) - _shownPerRow; + const auto bound = (now < 0) ? (_shownCount + now) : now; + setSelected(bound); + } else if (request.action == Qt::Key_Down) { + const auto now = std::max(_selected, 0) + _shownPerRow; + const auto bound = (now >= _shownCount) ? (now - _shownCount) : now; + setSelected(bound); } } @@ -357,17 +366,38 @@ void ChatSwitchProcess::layout(QSize size) { auto inner = outer.marginsRemoved(st::chatSwitchPadding); const auto available = inner.width(); const auto canPerRow = (available / st::chatSwitchSize.width()); + const auto canRows = (canPerRow > 2 * 7) + ? 1 + : (canPerRow > 3 * 4) + ? 2 + : 3; if (canPerRow < 1 || _list.empty()) { return; } const auto count = int(_list.size()); - const auto rows = (count + canPerRow - 1) / canPerRow; - const auto minPerRow = count / rows; - const auto wideRows = (count - (minPerRow * rows)); - const auto maxPerRow = wideRows ? (minPerRow + 1) : minPerRow; - const auto narrowShift = wideRows ? (st::chatSwitchSize.width() / 2) : 0; - const auto width = maxPerRow * st::chatSwitchSize.width(); - const auto height = rows * st::chatSwitchSize.height(); + _shownRows = std::min(canRows, (count + canPerRow - 1) / canPerRow); + _shownPerRow = std::min(count / _shownRows, canPerRow); + if (_shownRows > 2) { + if (_shownPerRow * 2 > _shownRows * 4) { + _shownRows = 2; + } else if (_shownPerRow > 4) { + _shownPerRow = 4; + } + } + if (_shownRows > 1) { + if (_shownPerRow > _shownRows * 7) { + _shownRows = 1; + } else if (_shownPerRow > 7) { + _shownPerRow = 7; + } + } + _shownCount = _shownPerRow * _shownRows; + if (_selected >= _shownCount) { + _selected = -1; + } + + const auto width = _shownPerRow * st::chatSwitchSize.width(); + const auto height = _shownRows * st::chatSwitchSize.height(); size = QSize(width, height); _inner = QRect( @@ -381,16 +411,19 @@ void ChatSwitchProcess::layout(QSize size) { auto index = 0; auto top = padding.top(); - for (auto row = 0; row != rows; ++row) { - const auto columns = (row < wideRows) ? maxPerRow : minPerRow; - auto left = padding.left() + ((row < wideRows) ? 0 : narrowShift); - for (auto column = 0; column != columns; ++column) { + for (auto row = 0; row != _shownRows; ++row) { + auto left = padding.left(); + for (auto column = 0; column != _shownPerRow; ++column) { auto &entry = _entries[index++]; entry.button->moveToLeft(left, top, _inner.width()); + entry.button->show(); left += st::chatSwitchSize.width(); } top += st::chatSwitchSize.height(); } + for (auto i = _shownRows * _shownPerRow; i < count; ++i) { + _entries[i].button->hide(); + } _shadowed = _outer.marginsAdded(st::boxRoundShadow.extend); _view->setGeometry(_shadowed); diff --git a/Telegram/SourceFiles/window/window_chat_switch_process.h b/Telegram/SourceFiles/window/window_chat_switch_process.h index 77173489ff..36c5f24c75 100644 --- a/Telegram/SourceFiles/window/window_chat_switch_process.h +++ b/Telegram/SourceFiles/window/window_chat_switch_process.h @@ -71,6 +71,9 @@ private: std::vector _entries; int _selected = -1; + int _shownRows = 0; + int _shownCount = 0; + int _shownPerRow = 0; rpl::event_stream> _chosen; rpl::event_stream<> _closeRequests;