Skip to content

Commit 5f3e4d9

Browse files
committed
Improve accessibility, don't let focusing unread bar.
1 parent f810c2b commit 5f3e4d9

4 files changed

Lines changed: 140 additions & 151 deletions

File tree

Telegram/SourceFiles/history/history_inner_widget.cpp

Lines changed: 66 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4083,25 +4083,22 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) {
40834083
const auto elements = accessibleElements();
40844084
const auto barIndex
40854085
= accessibilityUnreadBarIndex();
4086-
const auto elementIndex = (barIndex >= 0
4087-
&& _accessibilityFocusedIndex > barIndex)
4088-
? (_accessibilityFocusedIndex - 1)
4089-
: _accessibilityFocusedIndex;
4090-
if (elementIndex < 0
4091-
|| elementIndex >= int(elements.size())
4092-
|| elements[elementIndex]->data().get()
4093-
!= _accessibilityFocusedItem) {
4086+
if (accessibilityItemAtIndex(
4087+
_accessibilityFocusedIndex,
4088+
elements,
4089+
barIndex) != _accessibilityFocusedItem) {
40944090
// The focused item is still the same message, but
40954091
// its index in accessibleElements() shifted (the list
4096-
// was mutated since the last navigation). Repair the
4097-
// cached index in-place without emitting a focus
4098-
// change — the framework still thinks the focused
4099-
// child is _accessibilityFocusedItem and we are only
4100-
// catching up our bookkeeping. If the item is not in
4101-
// the loaded slice anymore the index is invalidated
4102-
// instead: selection and media actions dispatch by
4103-
// index, and a stale one would silently operate on
4104-
// whatever unrelated row occupies it now.
4092+
// was mutated since the last navigation, possibly by
4093+
// an unread bar appearing right at the cached index).
4094+
// Repair the cached index in-place without emitting a
4095+
// focus change — the framework still thinks the
4096+
// focused child is _accessibilityFocusedItem and we
4097+
// are only catching up our bookkeeping. If the item
4098+
// is not in the loaded slice anymore the index is
4099+
// invalidated instead: selection and media actions
4100+
// dispatch by index, and a stale one would silently
4101+
// operate on whatever unrelated row occupies it now.
41054102
_accessibilityFocusedIndex = -1;
41064103
for (auto i = 0, n = int(elements.size());
41074104
i < n; ++i) {
@@ -4115,6 +4112,13 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) {
41154112
}
41164113
}
41174114
}
4115+
} else if (_accessibilityFocusedIndex >= 0) {
4116+
// A nonnegative index with no cached item means the unread
4117+
// bar was focused. Follow the bar to wherever it sits now
4118+
// (rows inserted or removed above shift its index), or
4119+
// invalidate the focus when the bar is gone: the row that
4120+
// occupies the old index was never announced to the user.
4121+
_accessibilityFocusedIndex = accessibilityUnreadBarIndex();
41184122
}
41194123
const auto modifiers = e->modifiers()
41204124
& ~(Qt::KeypadModifier | Qt::GroupSwitchModifier);
@@ -4184,14 +4188,10 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) {
41844188
const auto elements = accessibleElements();
41854189
const auto barIndex
41864190
= accessibilityUnreadBarIndex();
4187-
const auto elementIndex = (barIndex >= 0
4188-
&& newIndex > barIndex)
4189-
? (newIndex - 1)
4190-
: newIndex;
4191-
const auto item = (elementIndex >= 0
4192-
&& elementIndex < int(elements.size()))
4193-
? elements[elementIndex]->data().get()
4194-
: nullptr;
4191+
const auto item = accessibilityItemAtIndex(
4192+
newIndex,
4193+
elements,
4194+
barIndex);
41954195
if (shiftRange) {
41964196
extendAccessibilitySelection(
41974197
_accessibilityFocusedIndex,
@@ -4213,12 +4213,8 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) {
42134213
}
42144214
}
42154215

4216-
if (_widget->markingMessagesRead()
4217-
&& (barIndex < 0 || newIndex != barIndex)
4218-
&& elementIndex >= 0
4219-
&& elementIndex < int(elements.size())) {
4220-
session().data().histories().readInboxTill(
4221-
elements[elementIndex]->data());
4216+
if (_widget->markingMessagesRead() && item) {
4217+
session().data().histories().readInboxTill(item);
42224218
}
42234219

42244220
e->accept();
@@ -5968,17 +5964,8 @@ void HistoryInner::extendAccessibilitySelection(
59685964
// towards it deselects the row being left.
59695965
const auto elements = accessibleElements();
59705966
const auto barIndex = accessibilityUnreadBarIndex();
5971-
const auto itemAt = [&](int index) -> HistoryItem* {
5972-
if (barIndex >= 0 && index == barIndex) {
5973-
return nullptr;
5974-
}
5975-
const auto elementIndex = (barIndex >= 0 && index > barIndex)
5976-
? (index - 1)
5977-
: index;
5978-
return (elementIndex >= 0
5979-
&& elementIndex < int(elements.size()))
5980-
? elements[elementIndex]->data().get()
5981-
: nullptr;
5967+
const auto itemAt = [&](int index) {
5968+
return accessibilityItemAtIndex(index, elements, barIndex);
59825969
};
59835970
if (oldIndex < 0) {
59845971
_accessibilitySelectionAnchor = itemAt(newIndex);
@@ -6024,22 +6011,14 @@ void HistoryInner::extendAccessibilitySelection(
60246011
}
60256012

60266013
void HistoryInner::playPauseFocusedMedia() {
6027-
if (_accessibilityFocusedIndex < 0) {
6028-
return;
6029-
}
6030-
const auto barIndex = accessibilityUnreadBarIndex();
6031-
if (barIndex >= 0 && _accessibilityFocusedIndex == barIndex) {
6032-
return;
6033-
}
60346014
const auto elements = accessibleElements();
6035-
const auto elementIndex = (barIndex >= 0
6036-
&& _accessibilityFocusedIndex > barIndex)
6037-
? (_accessibilityFocusedIndex - 1)
6038-
: _accessibilityFocusedIndex;
6039-
if (elementIndex < 0 || elementIndex >= int(elements.size())) {
6015+
const auto item = accessibilityItemAtIndex(
6016+
_accessibilityFocusedIndex,
6017+
elements,
6018+
accessibilityUnreadBarIndex());
6019+
if (!item) {
60406020
return;
60416021
}
6042-
const auto item = elements[elementIndex]->data();
60436022
if (const auto media = item->media()) {
60446023
if (const auto document = media->document()) {
60456024
if (document->isVoiceMessage()
@@ -6401,6 +6380,24 @@ int HistoryInner::accessibilityUnreadBarIndex() const {
64016380
return -1;
64026381
}
64036382

6383+
HistoryItem *HistoryInner::accessibilityItemAtIndex(
6384+
int index,
6385+
const std::vector<Element*> &elements,
6386+
int barIndex) const {
6387+
// The unread bar row maps to no item: a focused bar is cached as
6388+
// a null item with a nonnegative index, so it can never be
6389+
// mistaken for the message it is anchored to when rows shift.
6390+
if (index < 0 || (barIndex >= 0 && index == barIndex)) {
6391+
return nullptr;
6392+
}
6393+
const auto elementIndex = (barIndex >= 0 && index > barIndex)
6394+
? (index - 1)
6395+
: index;
6396+
return (elementIndex < int(elements.size()))
6397+
? elements[elementIndex]->data().get()
6398+
: nullptr;
6399+
}
6400+
64046401
int HistoryInner::accessibilityChildCount() const {
64056402
const auto barIndex = accessibilityUnreadBarIndex();
64066403
return int(accessibleElements().size()) + (barIndex >= 0 ? 1 : 0);
@@ -6612,6 +6609,13 @@ void HistoryInner::focusInEvent(QFocusEvent *e) {
66126609
// branch below establishes a fresh focus instead.
66136610
_accessibilityFocusedItem = nullptr;
66146611
_accessibilityFocusedIndex = -1;
6612+
} else if (_accessibilityFocusedIndex >= 0) {
6613+
// A nonnegative index with no cached item means the unread
6614+
// bar was focused. Follow the bar to wherever it sits now,
6615+
// or fall through to pick a fresh focus target when it is
6616+
// gone: the row that occupies the old index was never
6617+
// announced to the user.
6618+
_accessibilityFocusedIndex = accessibilityUnreadBarIndex();
66156619
}
66166620
if (_accessibilityFocusedIndex >= 0
66176621
&& _accessibilityFocusedIndex < count) {
@@ -6623,14 +6627,10 @@ void HistoryInner::focusInEvent(QFocusEvent *e) {
66236627
? (barIndex + 1)
66246628
: (count - 1);
66256629
const auto elements = accessibleElements();
6626-
const auto elementIndex = (barIndex >= 0
6627-
&& index > barIndex)
6628-
? (index - 1)
6629-
: index;
6630-
const auto item = (elementIndex >= 0
6631-
&& elementIndex < int(elements.size()))
6632-
? elements[elementIndex]->data().get()
6633-
: nullptr;
6630+
const auto item = accessibilityItemAtIndex(
6631+
index,
6632+
elements,
6633+
barIndex);
66346634
setAccessibilityFocusedItem(index, item);
66356635
});
66366636
}
@@ -6702,13 +6702,7 @@ void HistoryInner::applyAccessibilityFocus(
67026702
bool announceAlways) {
67036703
const auto elements = accessibleElements();
67046704
const auto barIndex = accessibilityUnreadBarIndex();
6705-
const auto elementIndex = (barIndex >= 0 && index > barIndex)
6706-
? (index - 1)
6707-
: index;
6708-
const auto item = (elementIndex >= 0
6709-
&& elementIndex < int(elements.size()))
6710-
? elements[elementIndex]->data().get()
6711-
: nullptr;
6705+
const auto item = accessibilityItemAtIndex(index, elements, barIndex);
67126706
const auto changed = (_accessibilityFocusedIndex != index)
67136707
|| (_accessibilityFocusedItem != item);
67146708
_accessibilitySelectionAnchor = nullptr;
@@ -6732,12 +6726,8 @@ void HistoryInner::applyAccessibilityFocus(
67326726
- (_visibleAreaBottom - _visibleAreaTop));
67336727
}
67346728
}
6735-
if (_widget->markingMessagesRead()
6736-
&& (barIndex < 0 || index != barIndex)
6737-
&& elementIndex >= 0
6738-
&& elementIndex < int(elements.size())) {
6739-
session().data().histories().readInboxTill(
6740-
elements[elementIndex]->data());
6729+
if (_widget->markingMessagesRead() && item) {
6730+
session().data().histories().readInboxTill(item);
67416731
}
67426732
}
67436733

Telegram/SourceFiles/history/history_inner_widget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,10 @@ class HistoryInner
310310
private:
311311
[[nodiscard]] std::vector<Element*> accessibleElements() const;
312312
[[nodiscard]] int accessibilityUnreadBarIndex() const;
313+
[[nodiscard]] HistoryItem *accessibilityItemAtIndex(
314+
int index,
315+
const std::vector<Element*> &elements,
316+
int barIndex) const;
313317
void toggleMessageSelection();
314318
void playPauseFocusedMedia();
315319
void setAccessibilityFocusedItem(int index, HistoryItem *item);

0 commit comments

Comments
 (0)