Fix: make screen readers announce correct details about TConsole instances (#6232)

This should close #6222.

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
This commit is contained in:
Stephen Lyons 2023-02-14 20:26:53 +00:00 committed by GitHub
parent bab6599bb6
commit 3c7593abed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 297 additions and 50 deletions

View file

@ -4081,3 +4081,23 @@ void Host::setFocusOnHostMainConsole()
mpConsole->activateWindow();
mpConsole->setFocus();
}
QPointer<TConsole> Host::parentTConsole(QObject* start) const
{
QPointer<TConsole> result;
auto ptr = start;
if (!ptr) {
// Handle pathalogical case:
return result;
}
do {
ptr = ptr->parent();
} while (ptr && !ptr->inherits("TConsole"));
// QObject::inherits(...) uses a const char* - so no need to wrap raw string literal!
if (!ptr) {
// Handle not found case:
return result;
}
result = qobject_cast<TConsole*>(ptr);
return result;
}

View file

@ -400,6 +400,7 @@ public:
bool caretEnabled() const;
void setCaretEnabled(bool enabled);
void setFocusOnHostMainConsole();
QPointer<TConsole> parentTConsole(QObject*) const;
cTelnet mTelnet;
QPointer<TMainConsole> mpConsole;

View file

@ -38,14 +38,16 @@
#include <QScrollBar>
#include "post_guard.h"
TCommandLine::TCommandLine(Host* pHost, CommandLineType type, TConsole* pConsole, QWidget* parent)
TCommandLine::TCommandLine(Host* pHost, const QString& name, CommandLineType type, TConsole* pConsole, QWidget* parent)
: QPlainTextEdit(parent)
, mCommandLineName(qsl("main"))
, mCommandLineName(name)
, mpHost(pHost)
, mType(type)
, mpKeyUnit(pHost->getKeyUnit())
, mpConsole(pConsole)
{
setObjectName(qsl("commandLine_%1_%2").arg(mpHost->getName(), name));
setAutoFillBackground(true);
setFocusPolicy(Qt::StrongFocus);
@ -74,6 +76,9 @@ TCommandLine::TCommandLine(Host* pHost, CommandLineType type, TConsole* pConsole
// We do NOT want the standard context menu to happen as we generate it
// ourself:
setContextMenuPolicy(Qt::PreventContextMenu);
connect(mudlet::self(), &mudlet::signal_adjustAccessibleNames, this, &TCommandLine::slot_adjustAccessibleNames);
slot_adjustAccessibleNames();
}
void TCommandLine::processNormalKey(QEvent* event)
@ -1288,3 +1293,103 @@ void TCommandLine::clearSuggestions()
{
commandLineSuggestions.clear();
}
void TCommandLine::slot_adjustAccessibleNames()
{
bool multipleProfilesActive = (mudlet::self()->getHostManager().getHostCount() > 1);
const QString hostName{mpHost ? mpHost->getName() : QString()};
switch (mType) {
case MainCommandLine:
if (multipleProfilesActive) {
setAccessibleName(tr("Input line for \"%1\" profile.",
// Intentional comment to separate arguments
"Accessibility-friendly name to describe the main command line for a "
"Mudlet profile when more than one profile is loaded, %1 is the "
"profile name. Because this is likely to be used often it should be "
"kept as short as possible.").arg(hostName));
setAccessibleDescription(tr("Type in text to send to the game server for the \"%1\" profile, or enter an alias "
"to run commands locally.",
// Intentional comment to separate arguments
"Accessibility-friendly description for the main command line for "
"a Mudlet profile when more than one profile is loaded, %1 is the "
"profile name. Because this is likely to be used often it should be "
"kept as short as possible.").arg(hostName));
} else {
setAccessibleName(tr("Input line.",
// Intentional comment to separate arguments
"Accessibility-friendly name to describe the main command line for a "
"Mudlet profile when only one profile is loaded. Because this is "
"likely to be used often it should be kept as short as possible."));
setAccessibleDescription(tr("Type in text to send to the game server, or enter an alias to run commands "
"locally.",
// Intentional comment to separate arguments
"Accessibility-friendly description for the main command line for "
"a Mudlet profile when only one profile is loaded. Because this is "
"likely to be used often it should be kept as short as possible."));
}
break;
case SubCommandLine:
if (multipleProfilesActive) {
setAccessibleName(tr("Additional input line \"%1\" on \"%2\" window of \"%3\"profile.",
// Intentional comment to separate arguments
"Accessibility-friendly name to describe an extra command line on "
"top of console/window when more than one profile is loaded, %1 is "
"the command line name, %2 is the name of the window/console that "
"it is on and %3 is the name of the profile.")
.arg(mCommandLineName, mpConsole->mConsoleName, hostName));
setAccessibleDescription(tr("Type in text to send to the game server for the \"%1\" profile, or enter an alias "
"to run commands locally.",
// Intentional comment to separate arguments
"Accessibility-friendly description for an extra command line on top of a "
"console/window when more than one profile is loaded, %1 is the profile "
"name.").arg(hostName));
} else {
setAccessibleName(tr("Additional input line \"%1\" on \"%2\" window.",
// Intentional comment to separate arguments
"Accessibility-friendly name to describe an extra command line on "
"top of console/window when only one profile is loaded, %1 is the "
"command line name and %2 is the name of the window/console that "
"it is on.")
.arg(mCommandLineName, mpConsole->mConsoleName));
setAccessibleDescription(tr("Type in text to send to the game server, or enter an alias to run commands "
"locally.",
// Intentional comment to separate arguments
"Accessibility-friendly description for an extra command line on "
"top of a console/window when only one profile is loaded."));
}
break;
case ConsoleCommandLine:
// The mCommandLine for this type is the same as the parent TConsole
if (multipleProfilesActive) {
setAccessibleName(tr("Input line of \"%1\" window of \"%2\" profile.",
// Intentional comment to separate arguments
"Accessibility-friendly name to describe the built-in command line of a "
"console/window other than the main one, when more than one profile is "
"loaded, %1 is the name of the window/console and %2 is the name of the "
"profile.").arg(mCommandLineName, hostName));
setAccessibleDescription(tr("Type in text to send to the game server for the \"%1\" profile, or enter an alias "
"to run commands locally.",
// Intentional comment to separate arguments
"Accessibility-friendly description for the built-in command line of a "
"console/window other than the main window's one when more than one profile is "
"loaded, %1 is the profile name.").arg(hostName));
} else {
setAccessibleName(tr("Input line of \"%1\" window.",
// Intentional comment to separate arguments
"Accessibility-friendly name to describe the built-in command line "
"of a console/window other than the main one, when only one "
"profile is loaded, %1 is the name of the window/console.")
.arg(mCommandLineName));
setAccessibleDescription(tr("Type in text to send to the game server, or enter an alias to run commands "
"locally.",
// Intentional comment to separate arguments
"Accessibility-friendly description for the built-in command line of a "
"console/window other than the main window's one when only one profile is "
"loaded."));
}
break;
case UnknownType:
Q_UNREACHABLE();
}
}

View file

@ -50,14 +50,14 @@ public:
enum CommandLineTypeFlag {
UnknownType = 0x0, // Should not be encountered but left as a trap value
MainCommandLine = 0x1, // One per profile
SubCommandLine = 0x2, // Overlaid on top of MainConsole instance, should be uniquely named in pool of SubCommandLine/SubConsole/UserWindow/Buffers AND Labels
ConsoleCommandLine = 0x4, // Integrated in MiniConsoles
SubCommandLine = 0x2, // Overlaid on top of TMainConsole or TConsole instance, should be uniquely named in pool of SubCommandLine/SubConsole/UserWindow/Buffers AND Labels
ConsoleCommandLine = 0x4, // Integrated in TConsoles other than those derived into a TMainConsole
};
Q_DECLARE_FLAGS(CommandLineType, CommandLineTypeFlag)
Q_DISABLE_COPY(TCommandLine)
explicit TCommandLine(Host*, CommandLineType type = UnknownType, TConsole* pConsole = nullptr, QWidget* parent = nullptr);
explicit TCommandLine(Host*, const QString&, CommandLineType type = UnknownType, TConsole* pConsole = nullptr, QWidget* parent = nullptr);
void focusInEvent(QFocusEvent*) override;
void focusOutEvent(QFocusEvent*) override;
void hideEvent(QHideEvent*) override;
@ -83,6 +83,7 @@ public slots:
void slot_addWord();
void slot_removeWord();
void slot_clearSelection(bool yes);
void slot_adjustAccessibleNames();
private:
bool event(QEvent*) override;

View file

@ -84,11 +84,9 @@ TConsole::TConsole(Host* pH, ConsoleType type, QWidget* parent)
ps->setContext(Qt::WidgetShortcut);
if (mType & CentralDebugConsole) {
setWindowTitle(tr("Debug Console"));
setAccessibleName(tr("Debug Console"));
setAccessibleDescription(tr("Debug messages are shown here."));
// Probably will not show up as this is used inside a QMainWindow widget
// which has its own title and icon set.
setWindowTitle(tr("Debug Console"));
// mIsSubConsole was left false for this
mWrapAt = 50;
} else {
@ -101,16 +99,6 @@ TConsole::TConsole(Host* pH, ConsoleType type, QWidget* parent)
mMainFrameLeftWidth = 0;
mMainFrameRightWidth = 0;
if (mType & ErrorConsole) {
setAccessibleName(tr("Error Console"));
setAccessibleDescription(tr("Error messages are shown here."));
} else if (mType & SubConsole) {
setAccessibleName(tr("Sub Console"));
setAccessibleDescription(tr("Sub console messages are shown here."));
} else {
setAccessibleName(tr("User Window"));
setAccessibleDescription(tr("User window messages are shown here."));
}
} else if (mType & (MainConsole|Buffer)) {
// Originally this was for TConsole instances without a parent pointer
// This branch for: Buffers, MainConsole
@ -122,8 +110,6 @@ TConsole::TConsole(Host* pH, ConsoleType type, QWidget* parent)
mCommandBgColor = mpHost->mCommandBgColor;
mCommandFgColor = mpHost->mCommandFgColor;
setAccessibleName(tr("Main Window"));
setAccessibleDescription(tr("Game content is shown here. It may contain subconsoles and a mapper window."));
} else {
Q_ASSERT_X(false, "TConsole::TConsole(...)", "invalid TConsole type detected");
}
@ -231,7 +217,7 @@ TConsole::TConsole(Host* pH, ConsoleType type, QWidget* parent)
centralLayout->setContentsMargins(0, 0, 0, 0);
if (mType == MainConsole) {
mpCommandLine = new TCommandLine(pH, mpCommandLine->MainCommandLine, this, mpMainDisplay);
mpCommandLine = new TCommandLine(pH, qsl("main"), TCommandLine::MainCommandLine, this, mpMainDisplay);
mpCommandLine->setContentsMargins(0, 0, 0, 0);
mpCommandLine->setSizePolicy(sizePolicy);
mpCommandLine->setFocusPolicy(Qt::StrongFocus);
@ -278,14 +264,10 @@ TConsole::TConsole(Host* pH, ConsoleType type, QWidget* parent)
setFocusProxy(mpCommandLine);
mUpperPane->setFocusProxy(mpCommandLine);
mLowerPane->setFocusProxy(mpCommandLine);
// technically this is the 'main input line' - but as it's the one most often used,
// it is important to keep its name short
mpCommandLine->setAccessibleName(qsl("input line"));
} else if (mType == UserWindow) {
setFocusProxy(mpHost->mpConsole->mpCommandLine);
mUpperPane->setFocusProxy(mpHost->mpConsole->mpCommandLine);
mLowerPane->setFocusProxy(mpHost->mpConsole->mpCommandLine);
mpHost->mpConsole->setAccessibleName(qsl("%1 input line").arg(mpHost->mpConsole->mConsoleName));
}
splitter->addWidget(mUpperPane);
@ -562,7 +544,8 @@ TConsole::TConsole(Host* pH, ConsoleType type, QWidget* parent)
mpCommandLine->adjustHeight();
}
adjustAccessibleNames();
connect(mudlet::self(), &mudlet::signal_adjustAccessibleNames, this, &TConsole::slot_adjustAccessibleNames);
slot_adjustAccessibleNames();
}
TConsole::~TConsole()
@ -1086,7 +1069,7 @@ void TConsole::scrollDown(int lines)
mUpperPane->updateScreenView();
mUpperPane->forceUpdate();
}
adjustAccessibleNames();
slot_adjustAccessibleNames();
}
void TConsole::scrollUp(int lines)
@ -1101,7 +1084,7 @@ void TConsole::scrollUp(int lines)
QTimer::singleShot(0, [this]() { mUpperPane->scrollUp(mLowerPane->getRowCount()); });
}
mUpperPane->scrollUp(lines);
adjustAccessibleNames();
slot_adjustAccessibleNames();
}
void TConsole::deselect()
@ -1454,15 +1437,13 @@ void TConsole::setCmdVisible(bool isVisible)
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// create MiniConsole commandline if it's not existing
if (!mpCommandLine) {
mpCommandLine = new TCommandLine(mpHost, mpCommandLine->ConsoleCommandLine, this, mpMainDisplay);
mpCommandLine = new TCommandLine(mpHost, mConsoleName, TCommandLine::ConsoleCommandLine, this, mpMainDisplay);
mpCommandLine->setContentsMargins(0, 0, 0, 0);
mpCommandLine->setSizePolicy(sizePolicy);
mpCommandLine->setFocusPolicy(Qt::StrongFocus);
// put this CommandLine in the mainConsoles SubCommandLineMap
// name is the console name
mpHost->mpConsole->mSubCommandLineMap[mConsoleName] = mpCommandLine;
mpCommandLine->mCommandLineName = mConsoleName;
mpCommandLine->setObjectName(mConsoleName);
layoutLayer2->addWidget(mpCommandLine);
}
if (mType == MainConsole) {
@ -2073,14 +2054,121 @@ void TConsole::mousePressEvent(QMouseEvent* event)
raiseMudletMousePressOrReleaseEvent(event, true);
}
void TConsole::adjustAccessibleNames()
void TConsole::slot_adjustAccessibleNames()
{
if (mLowerPane->isVisible()) {
mUpperPane->setAccessibleName(tr("main window past content", "accessibility-friendly name to describe the upper half of the Mudlet window when you've scrolled up"));
mLowerPane->setAccessibleName(tr("main window live content", "accessibility-friendly name to describe the lower half of the Mudlet window when you've scrolled up"));
} else {
mUpperPane->setAccessibleName(tr("main window"));
mLowerPane->setAccessibleName(QString());
bool multipleProfilesActive = (mudlet::self()->getHostManager().getHostCount() > 1);
switch (mType) {
case CentralDebugConsole:
setAccessibleName(tr("Debug Console."));
setAccessibleDescription(tr("Debug messages from all profile are shown here."));
if (mLowerPane->isVisible()) {
mUpperPane->setAccessibleName(tr("Central debug console past content.", "accessibility-friendly name to describe the upper half of the Mudlet central debug window when you've scrolled up"));
mLowerPane->setAccessibleName(tr("Central debug console live content.", "accessibility-friendly name to describe the lower half of the Mudlet central debug when you've scrolled up"));
} else {
mUpperPane->setAccessibleName(tr("Central debug console.", "accessibility-friendly name to describe the upper half of the Mudlet central debug window when it is not scrolled up"));
mLowerPane->setAccessibleName(QString());
}
return;
case ErrorConsole:
setAccessibleName(tr("Error Console in editor."));
if (mLowerPane->isVisible()) {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Editor's error window for profile \"%1\", past content.", "accessibility-friendly name to describe the upper half of the Mudlet profile's editor error window when you've scrolled up, %1 is the name of the profile when more than one is loaded.").arg(mProfileName));
mLowerPane->setAccessibleName(tr("Editor's error window for profile \"%1\", live content.", "accessibility-friendly name to describe the lower half of the Mudlet profile's editor error window when you've scrolled up, %1 is the name of the profile when more than one is loaded.").arg(mProfileName));
} else {
mUpperPane->setAccessibleName(tr("Editor's error window past content.", "accessibility-friendly name to describe the upper half of the Mudlet profile's editor error window when you've scrolled up and only one profile is loaded."));
mLowerPane->setAccessibleName(tr("Editor's error window live content.", "accessibility-friendly name to describe the lower half of the Mudlet profile's editor error window when you've scrolled up and only one profile is loaded."));
}
setAccessibleDescription(tr("Error messages for the \"%1\" profile are shown here in the editor.").arg(mProfileName));
} else {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Editor's error window for profile \"%1\".", "accessibility-friendly name to describe the upper half of the Mudlet profile's editor error window when it is not scrolled up, %1 is the name of the profile when more than one is loaded.").arg(mProfileName));
} else {
mUpperPane->setAccessibleName(tr("Editor's error window", "accessibility-friendly name to describe the upper half of the Mudlet profile's editor error window when it is not scrolled up and only one profile is loaded."));
}
mLowerPane->setAccessibleName(QString());
setAccessibleDescription(tr("Error messages are shown here in the editor."));
}
return;
case MainConsole:
setAccessibleDescription(tr("Game content is shown here. It may contain subconsoles and a mapper window."));
if (multipleProfilesActive) {
setAccessibleName(tr("Main Window for \"%1\" profile.").arg(mProfileName));
} else {
setAccessibleName(tr("Main Window."));
}
if (mLowerPane->isVisible()) {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Profile \"%1\" main window past content.", "accessibility-friendly name to describe the upper half of a Mudlet profile's main window when you've scrolled up, %1 is the name of the profile when more than one is loaded.").arg(mProfileName));
mLowerPane->setAccessibleName(tr("Profile \"%1\" main window live content.", "accessibility-friendly name to describe the lower half of a Mudlet profile's main window when you've scrolled up, %1 is the name of the profile when more than one is loaded.").arg(mProfileName));
} else {
mUpperPane->setAccessibleName(tr("Profile main window past content.", "accessibility-friendly name to describe the upper half of a Mudlet profile's main window when you've scrolled up and only one profile is loaded."));
mLowerPane->setAccessibleName(tr("Profile main window live content.", "accessibility-friendly name to describe the lower half of a Mudlet profile's main window when you've scrolled up and only one profile is loaded."));
}
} else {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Profile \"%1\" main window.", "accessibility-friendly name to describe the upper half of a Mudlet profile's main window when it is not scrolled up, %1 is the name of the profile when more than one is loaded.").arg(mProfileName));
} else {
mUpperPane->setAccessibleName(tr("Profile main window.", "accessibility-friendly name to describe the upper half of a Mudlet profile's main window when it is not scrolled up and only one profile is loaded."));
}
mLowerPane->setAccessibleName(QString());
}
return;
case SubConsole:
if (multipleProfilesActive) {
setAccessibleName(tr("Embedded window \"%1\" for \"%2\" profile.").arg(mConsoleName, mProfileName));
} else {
setAccessibleName(tr("Embedded window \"%1\".").arg(mConsoleName));
}
setAccessibleDescription(tr("Game content or locally generated text may be sent here."));
if (mLowerPane->isVisible()) {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Profile \"%1\" embedded window \"%2\" past content.", "accessibility-friendly name to describe the upper half of a Mudlet profile's sub-console window when you've scrolled up, %1 is the name of the profile when more than one is loaded and %2 is the name of the window.").arg(mProfileName, mConsoleName));
mLowerPane->setAccessibleName(tr("Profile \"%1\" embedded window \"%2\" live content.", "accessibility-friendly name to describe the lower half of a Mudlet profile's sub-console window when you've scrolled up, %1 is the name of the profile when more than one is loaded and %2 is the name of the window.").arg(mProfileName, mConsoleName));
} else {
mUpperPane->setAccessibleName(tr("Profile embedded window \"%1\" past content.", "accessibility-friendly name to describe the upper half of a Mudlet profile's sub-console window when you've scrolled up, %1 is the name of the window.").arg(mConsoleName));
mLowerPane->setAccessibleName(tr("Profile embedded window \"%1\" live content.", "accessibility-friendly name to describe the lower half of a Mudlet profile's sub-console window when you've scrolled up, %1 is the name of the window.").arg(mConsoleName));
}
} else {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Profile \"%1\" embedded window \"%2\".", "accessibility-friendly name to describe the upper half of a Mudlet profile's sub-console window when it is not scrolled up, %1 is the name of the profile when more than one is loaded and %2 is the name of the window.").arg(mProfileName, mConsoleName));
} else {
mUpperPane->setAccessibleName(tr("Profile embedded window \"%1\".", "accessibility-friendly name to describe the upper half of a Mudlet profile's sub-console window when it is not scrolled up, %1 is the name of the window.").arg(mConsoleName));
}
mLowerPane->setAccessibleName(QString());
}
return;
case UserWindow:
if (multipleProfilesActive) {
setAccessibleName(tr("User window \"%1\" for \"%2\" profile.").arg(mConsoleName, mProfileName));
} else {
setAccessibleName(tr("User window \"%1\".").arg(mConsoleName));
}
setAccessibleDescription(tr("Game content or locally generated text may be sent to this window that may be floated away from the Mudlet application or docked within the main application window."));
if (mLowerPane->isVisible()) {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Profile \"%1\" user window \"%2\" past content.", "accessibility-friendly name to describe the upper half of a Mudlet profile's floating/dockable user window window when you've scrolled up, %1 is the name of the profile when more than one is loaded and %2 is the name of the window.").arg(mProfileName, mConsoleName));
mLowerPane->setAccessibleName(tr("Profile \"%1\" user window \"%2\" live content.", "accessibility-friendly name to describe the lower half of a Mudlet profile's floating/dockable user window window when you've scrolled up, %1 is the name of the profile when more than one is loaded and %2 is the name of the window.").arg(mProfileName, mConsoleName));
} else {
mUpperPane->setAccessibleName(tr("Profile user window \"%1\" past content.", "accessibility-friendly name to describe the upper half of a Mudlet profile's sub-console window when you've scrolled up, %1 is the name of the window.").arg(mConsoleName));
mLowerPane->setAccessibleName(tr("Profile user window \"%1\" live content.", "accessibility-friendly name to describe the lower half of a Mudlet profile's sub-console window when you've scrolled up, %1 is the name of the window.").arg(mConsoleName));
}
} else {
if (multipleProfilesActive) {
mUpperPane->setAccessibleName(tr("Profile \"%1\" user window \"%2\".", "accessibility-friendly name to describe the upper half of a Mudlet profile's floating/dockable user window window when it is not scrolled up, %1 is the name of the profile when more than one is loaded and %2 is the name of the window.").arg(mProfileName, mConsoleName));
} else {
mUpperPane->setAccessibleName(tr("Profile user window \"%1\".", "accessibility-friendly name to describe the upper half of a Mudlet profile's floating/dockable user window window when it is not scrolled up, %1 is the name of the window.").arg(mConsoleName));
}
mLowerPane->setAccessibleName(QString());
}
return;
case Buffer:
// This is not a visible thing so is not accessible to screen readers
[[fallthrough]];
case UnknownType:
// Should never be used - and since we have now handled ALL enum values
// we do not need a "default:" entry
Q_UNREACHABLE();
}
}
@ -2089,7 +2177,7 @@ void TConsole::mouseReleaseEvent(QMouseEvent* event)
raiseMudletMousePressOrReleaseEvent(event, false);
}
void TConsole::TConsole::slot_changeControlCharacterHandling(const ControlCharacterMode mode)
void TConsole::slot_changeControlCharacterHandling(const ControlCharacterMode mode)
{
if (mControlCharacter != mode) {
mControlCharacter = mode;
@ -2104,6 +2192,7 @@ void TConsole::setCaretMode(bool enabled)
if (enabled) {
mUpperPane->initializeCaret();
// This adds TabFocus to the otherwise used ClickFocus:
mUpperPane->setFocusPolicy(Qt::StrongFocus);
mUpperPane->setFocusProxy(nullptr);
#if defined(Q_OS_WIN32) || defined(Q_OS_LINUX)
@ -2128,9 +2217,35 @@ void TConsole::setCaretMode(bool enabled)
QAccessibleEvent event(mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
} else if (mType == UserWindow) {
mUpperPane->setFocusProxy(mpHost->mpConsole->mpCommandLine);
QAccessibleEvent event(mpHost->mpConsole->mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
if (mpCommandLine && mpCommandLine->isVisible()) {
mUpperPane->setFocusProxy(mpCommandLine);
QAccessibleEvent event(mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
} else {
mUpperPane->setFocusProxy(mpHost->mpConsole->mpCommandLine);
QAccessibleEvent event(mpHost->mpConsole->mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
}
} else if (mType == SubConsole) {
if (mpCommandLine && mpCommandLine->isVisible()) {
mUpperPane->setFocusProxy(mpCommandLine);
QAccessibleEvent event(mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
} else {
// Need to search ancestors to find the TConsole that this one
// is inserted into
auto parentConsole = mpHost->parentTConsole(mpCommandLine);
if (!parentConsole.isNull()) {
parentConsole->mUpperPane->setFocusProxy(parentConsole->mpCommandLine);
QAccessibleEvent event(mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
} else {
// Somehow that has failed so fall back to the main console
mUpperPane->setFocusProxy(mpHost->mpConsole->mpCommandLine);
QAccessibleEvent event(mpHost->mpConsole->mpCommandLine, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
}
}
}
}

View file

@ -232,7 +232,7 @@ public:
//1 = unclicked/up; 2 = clicked/down, 0 is NOT valid:
int mButtonState = 1;
QString mConsoleName = qsl("main");
QString mConsoleName;
QString mCurrentLine;
QString mDisplayFontName = qsl("Bitstream Vera Sans Mono");
int mDisplayFontSize = 14;
@ -313,7 +313,7 @@ protected:
private:
void adjustAccessibleNames();
void slot_adjustAccessibleNames();
void createSearchOptionIcon();
ConsoleType mType = UnknownType;

View file

@ -477,7 +477,7 @@ void TMainConsole::resetMainConsole()
}
}
// This is a sub-console overlaid on to the main console
// This is a sub-console overlaid on to the main or other console
TConsole* TMainConsole::createMiniConsole(const QString& windowname, const QString& name, int x, int y, int width, int height)
{
//if pW then add Console as Overlay to the Userwindow
@ -741,15 +741,13 @@ std::pair<bool, QString> TMainConsole::createCommandLine(const QString& windowna
if (!pN) {
if (pS) {
pN = new TCommandLine(mpHost, mpCommandLine->SubCommandLine, this, pS->widget());
pN = new TCommandLine(mpHost, name, TCommandLine::SubCommandLine, this, pS->widget());
} else if (pW) {
pN = new TCommandLine(mpHost, mpCommandLine->SubCommandLine, this, pW->widget());
pN = new TCommandLine(mpHost, name, TCommandLine::SubCommandLine, this, pW->widget());
} else {
pN = new TCommandLine(mpHost, mpCommandLine->SubCommandLine, this, mpMainFrame);
pN = new TCommandLine(mpHost, name, TCommandLine::SubCommandLine, this, mpMainFrame);
}
mSubCommandLineMap[name] = pN;
pN->mCommandLineName = name;
pN->setObjectName(name);
pN->resize(width, height);
pN->move(x, y);
pN->show();

View file

@ -1581,6 +1581,7 @@ void dlgConnectionProfiles::loadProfile(bool alsoConnect)
mudlet::self()->updateMultiViewControls();
emit mudlet::self()->signal_hostCreated(pHost, hostManager.getHostCount());
emit mudlet::self()->signal_adjustAccessibleNames();
emit signal_load_profile(profile_name, alsoConnect);
}

View file

@ -3412,6 +3412,8 @@ void dlgProfilePreferences::slot_handleHostAddition(Host* pHost, const quint8 co
* functionality to handle the situation of having a mainly disabled preference
* dialog opened when no profiles were, it makes for a slightly more friendly
* UX to also do this and adds a certain "balance" in the "code functionality".
* Note that although pHost is not equal to nullptr when this is called, it is
* now NOT valid or safe to dereference!
*/
void dlgProfilePreferences::slot_handleHostDeletion(Host* pHost)
{

View file

@ -605,6 +605,7 @@ mudlet::mudlet()
// initialize Announcer after the window is loaded, as UIA on Windows requires it
QTimer::singleShot(0, this, [this]() {
mpAnnouncer = new Announcer(this);
emit signal_adjustAccessibleNames();
});
}
@ -1318,6 +1319,7 @@ void mudlet::closeHost(const QString& name)
int hostCount = mHostManager.getHostCount();
emit signal_hostDestroyed(pH, --hostCount);
mHostManager.deleteHost(pH->getName());
emit signal_adjustAccessibleNames();
updateMultiViewControls();
}
@ -2697,6 +2699,7 @@ void mudlet::doAutoLogin(const QString& profile_name)
}
emit signal_hostCreated(pHost, mHostManager.getHostCount());
emit signal_adjustAccessibleNames();
slot_connectionDialogueFinished(profile_name, true);
enableToolbarButtons();
updateMultiViewControls();

View file

@ -519,6 +519,7 @@ protected:
signals:
void signal_adjustAccessibleNames();
void signal_appearanceChanged(mudlet::Appearance);
void signal_editorTextOptionsChanged(QTextOption::Flags);
void signal_enableFulScreenModeChanged(bool);