init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
131
Telegram/lib_ui/ui/accessible/ui_accessible_widget.cpp
Normal file
131
Telegram/lib_ui/ui/accessible/ui_accessible_widget.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "ui/accessible/ui_accessible_widget.h"
|
||||
|
||||
#include "base/debug_log.h"
|
||||
#include "base/integration.h"
|
||||
#include "base/screen_reader_state.h"
|
||||
#include "base/timer.h"
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace Ui::Accessible {
|
||||
namespace {
|
||||
|
||||
constexpr auto kCleanupDelay = 5 * crl::time(1000);
|
||||
|
||||
class FocusManager final {
|
||||
public:
|
||||
FocusManager();
|
||||
|
||||
void registerWidget(not_null<RpWidget*> widget);
|
||||
|
||||
private:
|
||||
void cleanup();
|
||||
|
||||
std::vector<QPointer<RpWidget>> _widgets;
|
||||
base::Timer _cleanupTimer;
|
||||
bool _active = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
FocusManager::FocusManager() : _cleanupTimer([=] { cleanup(); }) {
|
||||
base::ScreenReaderState::Instance()->activeValue(
|
||||
) | rpl::on_next([=](bool active) {
|
||||
_active = active;
|
||||
LOG(("Screen Reader: %1").arg(active ? "active" : "inactive"));
|
||||
|
||||
cleanup();
|
||||
for (const auto &widget : _widgets) {
|
||||
widget->setFocusPolicy(active ? Qt::TabFocus : Qt::NoFocus);
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void FocusManager::registerWidget(not_null<RpWidget*> widget) {
|
||||
const auto role = widget->accessibilityRole();
|
||||
if (role != QAccessible::Role::Button
|
||||
&& role != QAccessible::Role::Link
|
||||
&& role != QAccessible::Role::CheckBox
|
||||
&& role != QAccessible::Role::Slider) {
|
||||
return;
|
||||
}
|
||||
if (_active) {
|
||||
widget->setFocusPolicy(Qt::TabFocus);
|
||||
}
|
||||
_widgets.push_back(widget.get());
|
||||
if (!_cleanupTimer.isActive()) {
|
||||
_cleanupTimer.callOnce(kCleanupDelay);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusManager::cleanup() {
|
||||
_widgets.erase(
|
||||
ranges::remove_if(
|
||||
_widgets,
|
||||
[](const QPointer<RpWidget> &widget) { return !widget; }),
|
||||
end(_widgets));
|
||||
}
|
||||
|
||||
[[nodiscard]] FocusManager &Manager() {
|
||||
static FocusManager Instance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Widget::Widget(not_null<RpWidget*> widget) : QAccessibleWidget(widget) {
|
||||
Manager().registerWidget(widget);
|
||||
}
|
||||
|
||||
[[nodiscard]] not_null<RpWidget*> Widget::rp() const {
|
||||
return static_cast<RpWidget*>(widget());
|
||||
}
|
||||
|
||||
QAccessible::Role Widget::role() const {
|
||||
return rp()->accessibilityRole();
|
||||
}
|
||||
|
||||
QAccessible::State Widget::state() const {
|
||||
auto result = QAccessibleWidget::state();
|
||||
rp()->accessibilityState().writeTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList Widget::actionNames() const {
|
||||
return QAccessibleWidget::actionNames()
|
||||
+ rp()->accessibilityActionNames();
|
||||
}
|
||||
|
||||
void Widget::doAction(const QString &actionName) {
|
||||
QAccessibleWidget::doAction(actionName);
|
||||
base::Integration::Instance().enterFromEventLoop([&] {
|
||||
rp()->accessibilityDoAction(actionName);
|
||||
});
|
||||
}
|
||||
|
||||
QString Widget::text(QAccessible::Text t) const {
|
||||
const auto result = QAccessibleWidget::text(t);
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
switch (t) {
|
||||
case QAccessible::Name: {
|
||||
return rp()->accessibilityName();
|
||||
}
|
||||
case QAccessible::Description: {
|
||||
return rp()->accessibilityDescription();
|
||||
}
|
||||
case QAccessible::Value: {
|
||||
return rp()->accessibilityValue();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Ui::Accessible
|
||||
Reference in New Issue
Block a user