mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-20 08:03:45 +08:00
Fixed reverse focus order on Shift+Tab in input fields.
This commit is contained in:
@@ -1579,15 +1579,16 @@ void EditNameBox::prepare() {
|
||||
_last->submits(
|
||||
) | rpl::on_next([=] { submit(); }, _last->lifetime());
|
||||
|
||||
using TabbedRequest = Ui::InputField::TabbedRequest;
|
||||
_first->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
_last->setFocus();
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}, _first->lifetime());
|
||||
_last->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
_first->setFocus();
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}, _last->lifetime());
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +154,7 @@ public:
|
||||
bool refreshStaleMedia(crl::time threshold);
|
||||
[[nodiscard]] std::vector<PollAnswer> toPollAnswers() const;
|
||||
void focusFirst();
|
||||
void focusLast();
|
||||
|
||||
void enableChooseCorrect(bool enabled, bool multiCorrect = false);
|
||||
|
||||
@@ -161,7 +162,7 @@ public:
|
||||
[[nodiscard]] rpl::producer<int> usedCount() const;
|
||||
[[nodiscard]] rpl::producer<not_null<QWidget*>> scrollToWidget() const;
|
||||
[[nodiscard]] rpl::producer<> backspaceInFront() const;
|
||||
[[nodiscard]] rpl::producer<> tabbed() const;
|
||||
[[nodiscard]] rpl::producer<bool> tabbed() const;
|
||||
|
||||
void handlePaste(
|
||||
not_null<Ui::InputField*> field,
|
||||
@@ -280,7 +281,7 @@ private:
|
||||
bool _hasCorrect = false;
|
||||
rpl::event_stream<not_null<QWidget*>> _scrollToWidget;
|
||||
rpl::event_stream<> _backspaceInFront;
|
||||
rpl::event_stream<> _tabbed;
|
||||
rpl::event_stream<bool> _tabbed;
|
||||
rpl::lifetime _emojiPanelLifetime;
|
||||
|
||||
};
|
||||
@@ -829,7 +830,7 @@ rpl::producer<> Options::backspaceInFront() const {
|
||||
return _backspaceInFront.events();
|
||||
}
|
||||
|
||||
rpl::producer<> Options::tabbed() const {
|
||||
rpl::producer<bool> Options::tabbed() const {
|
||||
return _tabbed.events();
|
||||
}
|
||||
|
||||
@@ -870,6 +871,12 @@ void Options::focusFirst() {
|
||||
_list.front()->setFocus();
|
||||
}
|
||||
|
||||
void Options::focusLast() {
|
||||
Expects(!_list.empty());
|
||||
|
||||
_list.back()->setFocus();
|
||||
}
|
||||
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> Options::createChooseCorrectGroup() {
|
||||
auto result = std::make_shared<Ui::RadiobuttonGroup>(0);
|
||||
result->setChangedCallback([=](int) {
|
||||
@@ -1093,14 +1100,20 @@ void Options::initOptionField(not_null<Ui::InputField*> field) {
|
||||
_scrollToWidget.fire_copy(field);
|
||||
}, field->lifetime());
|
||||
field->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<Ui::InputField::TabbedRequest*> request) {
|
||||
const auto index = findField(field);
|
||||
if (index + 1 < _list.size()) {
|
||||
if (request->backward) {
|
||||
if (index > 0) {
|
||||
_list[index - 1]->setFocus();
|
||||
} else {
|
||||
_tabbed.fire(true);
|
||||
}
|
||||
} else if (index + 1 < _list.size()) {
|
||||
_list[index + 1]->setFocus();
|
||||
} else {
|
||||
_tabbed.fire({});
|
||||
_tabbed.fire(false);
|
||||
}
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}, field->lifetime());
|
||||
base::install_event_filter(field, [=](not_null<QEvent*> event) {
|
||||
if (event->type() != QEvent::KeyPress
|
||||
@@ -2758,16 +2771,15 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
st::boxDividerLabel),
|
||||
st::createPollLimitPadding));
|
||||
|
||||
question->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
description->setFocus();
|
||||
*handled = true;
|
||||
}, question->lifetime());
|
||||
|
||||
using TabbedRequest = Ui::InputField::TabbedRequest;
|
||||
description->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
options->focusFirst();
|
||||
*handled = true;
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
if (request->backward) {
|
||||
question->setFocus();
|
||||
} else {
|
||||
options->focusFirst();
|
||||
}
|
||||
request->handled = true;
|
||||
}, description->lifetime());
|
||||
|
||||
Ui::AddSkip(container);
|
||||
@@ -3061,9 +3073,23 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
rpl::single(quiz->toggled()) | rpl::then(quiz->toggledChanges()));
|
||||
addMediaButton(solution, state->solutionMedia);
|
||||
|
||||
question->tabbed(
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
if (!request->backward) {
|
||||
description->setFocus();
|
||||
} else if (quiz->toggled()) {
|
||||
solution->setFocus();
|
||||
} else {
|
||||
options->focusLast();
|
||||
}
|
||||
request->handled = true;
|
||||
}, question->lifetime());
|
||||
|
||||
options->tabbed(
|
||||
) | rpl::on_next([=] {
|
||||
if (quiz->toggled()) {
|
||||
) | rpl::on_next([=](bool backward) {
|
||||
if (backward) {
|
||||
description->setFocus();
|
||||
} else if (quiz->toggled()) {
|
||||
solution->setFocus();
|
||||
} else {
|
||||
question->setFocus();
|
||||
@@ -3071,9 +3097,13 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
}, question->lifetime());
|
||||
|
||||
solution->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
question->setFocus();
|
||||
*handled = true;
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
if (request->backward) {
|
||||
options->focusLast();
|
||||
} else {
|
||||
question->setFocus();
|
||||
}
|
||||
request->handled = true;
|
||||
}, solution->lifetime());
|
||||
|
||||
const auto updateAddOptionsLocked = [=] {
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
[[nodiscard]] bool isValid() const;
|
||||
[[nodiscard]] std::vector<TodoListItem> toTodoListItems() const;
|
||||
void focusFirst();
|
||||
void focusLast();
|
||||
|
||||
[[nodiscard]] rpl::producer<int> addedCount() const;
|
||||
[[nodiscard]] rpl::producer<not_null<QWidget*>> scrollToWidget() const;
|
||||
@@ -579,6 +580,12 @@ void Tasks::focusFirst() {
|
||||
FocusAtEnd((_list.begin() + locked)->get()->field());
|
||||
}
|
||||
|
||||
void Tasks::focusLast() {
|
||||
Expects(!_list.empty());
|
||||
|
||||
_list.back()->setFocus();
|
||||
}
|
||||
|
||||
bool Tasks::correctShadows() const {
|
||||
// Last one should be without shadow.
|
||||
const auto noShadow = ranges::find(
|
||||
@@ -763,14 +770,21 @@ void Tasks::initTaskField(not_null<Task*> task, TextWithEntities text) {
|
||||
_scrollToWidget.fire_copy(field);
|
||||
}, field->lifetime());
|
||||
field->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<Ui::InputField::TabbedRequest*> request) {
|
||||
const auto index = findField(field);
|
||||
if (index + 1 < _list.size()) {
|
||||
if (request->backward) {
|
||||
const auto locked = _existingLocked ? _existingCount : 0;
|
||||
if (index > locked) {
|
||||
_list[index - 1]->setFocus();
|
||||
} else {
|
||||
_tabbed.fire({});
|
||||
}
|
||||
} else if (index + 1 < _list.size()) {
|
||||
_list[index + 1]->setFocus();
|
||||
} else {
|
||||
_tabbed.fire({});
|
||||
}
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}, field->lifetime());
|
||||
base::install_event_filter(field, [=](not_null<QEvent*> event) {
|
||||
if (event->type() != QEvent::KeyPress
|
||||
@@ -1041,9 +1055,13 @@ object_ptr<Ui::RpWidget> EditTodoListBox::setupContent() {
|
||||
st::createPollLimitPadding));
|
||||
|
||||
title->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
tasks->focusFirst();
|
||||
*handled = true;
|
||||
) | rpl::on_next([=](not_null<Ui::InputField::TabbedRequest*> request) {
|
||||
if (request->backward) {
|
||||
tasks->focusLast();
|
||||
} else {
|
||||
tasks->focusFirst();
|
||||
}
|
||||
request->handled = true;
|
||||
}, title->lifetime());
|
||||
|
||||
Ui::AddSkip(container);
|
||||
|
||||
@@ -1955,10 +1955,10 @@ void InitFieldAutocomplete(
|
||||
}
|
||||
|
||||
field->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<Ui::InputField::TabbedRequest*> request) {
|
||||
if (!raw->isHidden()) {
|
||||
raw->chooseSelected(FieldAutocomplete::ChooseMethod::ByTab);
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}
|
||||
}, raw->lifetime());
|
||||
|
||||
|
||||
@@ -276,21 +276,22 @@ void EditLinkBox(
|
||||
}
|
||||
};
|
||||
|
||||
using TabbedRequest = Ui::InputField::TabbedRequest;
|
||||
url->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
clearFullSelection(url);
|
||||
text->setFocus();
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}, url->lifetime());
|
||||
|
||||
text->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<TabbedRequest*> request) {
|
||||
if (!url->empty()) {
|
||||
url->selectAll();
|
||||
}
|
||||
clearFullSelection(text);
|
||||
url->setFocus();
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}, text->lifetime());
|
||||
}
|
||||
|
||||
|
||||
@@ -458,10 +458,10 @@ HistoryWidget::HistoryWidget(
|
||||
escape();
|
||||
}, _field->lifetime());
|
||||
_field->tabbed(
|
||||
) | rpl::on_next([=](not_null<bool*> handled) {
|
||||
) | rpl::on_next([=](not_null<Ui::InputField::TabbedRequest*> request) {
|
||||
if (_supportAutocomplete) {
|
||||
_supportAutocomplete->activate(_field.data());
|
||||
*handled = true;
|
||||
request->handled = true;
|
||||
}
|
||||
}, _field->lifetime());
|
||||
_field->heightChanges(
|
||||
|
||||
Submodule Telegram/lib_ui updated: 84ab0a4bbc...3b58165640
Reference in New Issue
Block a user