Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions frontend/OBSApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ UncleanLaunchAction handleUncleanShutdown(bool enableCrashUpload)

return launchAction;
}

QAccessibleInterface *alignmentSelectorFactory(const QString &classname, QObject *object)
{
if (classname == QLatin1String("AlignmentSelector")) {
if (auto *w = qobject_cast<AlignmentSelector *>(object))
return new AccessibleAlignmentSelector(w);
}
return nullptr;
}
} // namespace

QObject *CreateShortcutFilter()
Expand Down Expand Up @@ -1022,6 +1031,8 @@ void OBSApp::AppInit()
{
ProfileScope("OBSApp::AppInit");

QAccessible::installFactory(alignmentSelectorFactory);

if (!MakeUserDirs())
throw "Failed to create required user directories";
if (!InitGlobalConfig())
Expand Down
6 changes: 6 additions & 0 deletions frontend/cmake/ui-components.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ target_sources(
PRIVATE
components/AbsoluteSlider.cpp
components/AbsoluteSlider.hpp
components/AccessibleAlignmentCell.cpp
components/AccessibleAlignmentCell.hpp
components/AccessibleAlignmentSelector.cpp
components/AccessibleAlignmentSelector.hpp
components/AlignmentSelector.cpp
components/AlignmentSelector.hpp
components/ApplicationAudioCaptureToolbar.cpp
components/ApplicationAudioCaptureToolbar.hpp
components/AudioCaptureToolbar.cpp
Expand Down
71 changes: 71 additions & 0 deletions frontend/components/AccessibleAlignmentCell.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/******************************************************************************
Copyright (C) 2025 by Taylor Giampaolo <warchamp7@obsproject.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include "AccessibleAlignmentCell.hpp"

#include <OBSApp.hpp>

using namespace std::string_view_literals;
constexpr std::array indexToStrings = {
"Basic.TransformWindow.Alignment.TopLeft"sv, "Basic.TransformWindow.Alignment.TopCenter"sv,
"Basic.TransformWindow.Alignment.TopRight"sv, "Basic.TransformWindow.Alignment.CenterLeft"sv,
"Basic.TransformWindow.Alignment.Center"sv, "Basic.TransformWindow.Alignment.CenterRight"sv,
"Basic.TransformWindow.Alignment.BottomLeft"sv, "Basic.TransformWindow.Alignment.BottomCenter"sv,
"Basic.TransformWindow.Alignment.BottomRight"sv};

AccessibleAlignmentCell::AccessibleAlignmentCell(QAccessibleInterface *parent, AlignmentSelector *widget, int index)
: parent_(parent),
widget(widget),
index_(index)
{
}

QRect AccessibleAlignmentCell::rect() const
{
return widget->cellRect(index_);
}

QString AccessibleAlignmentCell::text(QAccessible::Text text) const
{
if (text == QAccessible::Name || text == QAccessible::Value) {
return QString(indexToStrings[index_].data());
}
return QString();
}

QAccessible::State AccessibleAlignmentCell::state() const
{
QAccessible::State state;
bool enabled = widget->isEnabled();

bool isSelectedCell = widget->currentIndex() == index_;
bool isFocusedCell = widget->focusedCell == index_;

state.disabled = !enabled;
state.focusable = enabled;
state.focused = widget->hasFocus() && isFocusedCell;
state.checkable = true;
state.checked = isSelectedCell;
state.selected = isSelectedCell;

return state;
}

QAccessible::Role AccessibleAlignmentCell::role() const
{
return QAccessible::CheckBox;
}
51 changes: 51 additions & 0 deletions frontend/components/AccessibleAlignmentCell.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/******************************************************************************
Copyright (C) 2025 by Taylor Giampaolo <warchamp7@obsproject.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#pragma once

#include <components/AlignmentSelector.hpp>

#include <QAccessibleInterface>
#include <QRect>

class AlignmentSelector;

class AccessibleAlignmentCell : public QAccessibleInterface {
QAccessibleInterface *parent_;
AlignmentSelector *widget;
int index_;

public:
AccessibleAlignmentCell(QAccessibleInterface *parent, AlignmentSelector *widget, int index);

int index() const { return index_; }

QRect rect() const override;
QString text(QAccessible::Text t) const override;
QAccessible::State state() const override;
QAccessible::Role role() const override;

QObject *object() const override { return nullptr; }
QAccessibleInterface *child(int) const override { return nullptr; }
QAccessibleInterface *childAt(int, int) const override { return nullptr; }
int childCount() const override { return 0; }
int indexOfChild(const QAccessibleInterface *) const override { return -1; }
QAccessibleInterface *parent() const override { return parent_; }
QAccessibleInterface *focusChild() const override { return nullptr; }
bool isValid() const override { return widget != nullptr; }
void setText(QAccessible::Text, const QString &) override {}
};
126 changes: 126 additions & 0 deletions frontend/components/AccessibleAlignmentSelector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/******************************************************************************
Copyright (C) 2025 by Taylor Giampaolo <warchamp7@obsproject.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include "AccessibleAlignmentSelector.hpp"

#include <OBSApp.hpp>

AccessibleAlignmentSelector::AccessibleAlignmentSelector(AlignmentSelector *widget_)
: QAccessibleWidget(widget_, QAccessible::Grouping)
{
for (int i = 0; i < cellCount; ++i) {
AccessibleAlignmentCell *cell = new AccessibleAlignmentCell(this, widget_, i);
QAccessible::registerAccessibleInterface(cell);
cellInterfaces.insert(i, QAccessible::uniqueId(cell));
}
}

AccessibleAlignmentSelector::~AccessibleAlignmentSelector()
{
for (QAccessible::Id id : std::as_const(cellInterfaces)) {
QAccessible::deleteAccessibleInterface(id);
}
}

int AccessibleAlignmentSelector::childCount() const
{
return cellCount;
}

QAccessibleInterface *AccessibleAlignmentSelector::child(int index) const
{
if (QAccessible::Id id = cellInterfaces.value(index)) {
return QAccessible::accessibleInterface(id);
}

return nullptr;
}

int AccessibleAlignmentSelector::indexOfChild(const QAccessibleInterface *child) const
{
if (!child) {
return -1;
}

QAccessible::Id id = QAccessible::uniqueId(const_cast<QAccessibleInterface *>(child));
return cellInterfaces.key(id, -1);
}

bool AccessibleAlignmentSelector::isValid() const
{
return widget() != nullptr;
}

QAccessibleInterface *AccessibleAlignmentSelector::focusChild() const
{
for (int i = 0; i < childCount(); ++i) {
if (child(i)->state().focused) {
return child(i);
}
}
return nullptr;
}

QRect AccessibleAlignmentSelector::rect() const
{
return widget()->rect();
}

QString AccessibleAlignmentSelector::text(QAccessible::Text textType) const
{
if (textType == QAccessible::Name) {
QString str = widget()->accessibleName();
if (str.isEmpty()) {
str = QTStr("Accessible.Widget.Name.AlignmentSelector");
}
return str;
}

if (textType == QAccessible::Value) {
return value().toString();
}

return QAccessibleWidget::text(textType);
}

QAccessible::Role AccessibleAlignmentSelector::role() const
{
return QAccessible::Grouping;
}

QAccessible::State AccessibleAlignmentSelector::state() const
{
QAccessible::State state;

state.focusable = true;
state.focused = widget()->hasFocus();
state.disabled = !widget()->isEnabled();
state.readOnly = false;

return state;
}

QVariant AccessibleAlignmentSelector::value() const
{
for (int i = 0; i < childCount(); ++i) {
if (child(i)->state().checked) {
return child(i)->text(QAccessible::Name);
}
}

return QTStr("None");
}
47 changes: 47 additions & 0 deletions frontend/components/AccessibleAlignmentSelector.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/******************************************************************************
Copyright (C) 2025 by Taylor Giampaolo <warchamp7@obsproject.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#pragma once

#include <components/AccessibleAlignmentCell.hpp>

#include <QAccessible>
#include <QAccessibleInterface>
#include <QAccessibleWidget>

class AlignmentSelector;

class AccessibleAlignmentSelector : public QAccessibleWidget {
mutable QHash<int, QAccessible::Id> cellInterfaces{};
static constexpr int cellCount = 9;

public:
explicit AccessibleAlignmentSelector(AlignmentSelector *widget);
~AccessibleAlignmentSelector();

QRect rect() const override;
QAccessible::Role role() const override;
QAccessible::State state() const override;
QString text(QAccessible::Text t) const override;
QAccessibleInterface *child(int index) const override;
int childCount() const override;
int indexOfChild(const QAccessibleInterface *child) const override;
bool isValid() const override;
QAccessibleInterface *focusChild() const override;

QVariant value() const;
};
Loading
Loading