diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/plugins/platforms/android/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/plugins/platforms/android/androidjniaccessibility.cpp | 130 | ||||
-rw-r--r-- | src/plugins/styles/modernwindows/qwindows11style.cpp | 213 |
4 files changed, 241 insertions, 111 deletions
diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt index f30c27c24be..498a0772bc9 100644 --- a/src/plugins/platforms/CMakeLists.txt +++ b/src/plugins/platforms/CMakeLists.txt @@ -4,10 +4,10 @@ if(ANDROID) add_subdirectory(android) endif() -if(NOT ANDROID AND NOT WASM) +if(NOT WASM) add_subdirectory(minimal) endif() -if(QT_FEATURE_freetype AND NOT ANDROID AND NOT WASM) +if(QT_FEATURE_freetype AND NOT WASM) add_subdirectory(offscreen) endif() if(QT_FEATURE_xcb) diff --git a/src/plugins/platforms/android/CMakeLists.txt b/src/plugins/platforms/android/CMakeLists.txt index 0160e12c26c..0d2a048abde 100644 --- a/src/plugins/platforms/android/CMakeLists.txt +++ b/src/plugins/platforms/android/CMakeLists.txt @@ -51,7 +51,12 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin qandroidplatformdialoghelpers.cpp # Conflicting JNI classes, and types androidcontentfileengine.cpp + qandroidplatformforeignwindow.cpp qandroidplatformintegration.cpp + qandroidplatformscreen.cpp + qandroidplatformservices.cpp + qandroidplatformwindow.cpp + qandroidsystemlocale.cpp INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ${QtBase_SOURCE_DIR}/src/3rdparty/android diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index 200c2f7a47b..b3ff0a4f06e 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -28,6 +28,7 @@ using namespace Qt::StringLiterals; namespace QtAndroidAccessibility { + static jmethodID m_setClassNameMethodID = 0; static jmethodID m_addActionMethodID = 0; static jmethodID m_setCheckableMethodID = 0; static jmethodID m_setCheckedMethodID = 0; @@ -421,6 +422,130 @@ namespace QtAndroidAccessibility return jstr; } + static QString classNameForRole(QAccessible::Role role, QAccessible::State state) { + switch (role) { + case QAccessible::Role::Button: + case QAccessible::Role::Link: + { + if (state.checkable) + // There is also a android.widget.Switch for which we have no match. + return QStringLiteral("android.widget.ToggleButton"); + return QStringLiteral("android.widget.Button"); + } + case QAccessible::Role::CheckBox: + // As of android/accessibility/utils/Role.java::getRole a CheckBox + // is NOT android.widget.CheckBox + return QStringLiteral("android.widget.CompoundButton"); + case QAccessible::Role::Clock: + return QStringLiteral("android.widget.TextClock"); + case QAccessible::Role::ComboBox: + return QStringLiteral("android.widget.Spinner"); + case QAccessible::Role::Graphic: + // QQuickImage does not provide this role it inherits Client from QQuickItem + return QStringLiteral("android.widget.ImageView"); + case QAccessible::Role::Grouping: + return QStringLiteral("android.view.ViewGroup"); + case QAccessible::Role::List: + // As of android/accessibility/utils/Role.java::getRole a List + // is NOT android.widget.ListView + return QStringLiteral("android.widget.AbsListView"); + case QAccessible::Role::MenuItem: + return QStringLiteral("android.view.MenuItem"); + case QAccessible::Role::PopupMenu: + return QStringLiteral("android.widget.PopupMenu"); + case QAccessible::Role::Separator: + return QStringLiteral("android.widget.Space"); + case QAccessible::Role::ToolBar: + return QStringLiteral("android.view.Toolbar"); + case QAccessible::Role::Heading: [[fallthrough]]; + case QAccessible::Role::StaticText: + // Heading vs. regular Text is finally determined by AccessibilityNodeInfo.isHeading() + return QStringLiteral("android.widget.TextView"); + case QAccessible::Role::EditableText: + return QStringLiteral("android.widget.EditText"); + case QAccessible::Role::RadioButton: + return QStringLiteral("android.widget.RadioButton"); + case QAccessible::Role::ProgressBar: + return QStringLiteral("android.widget.ProgressBar"); + // Range information need to be filled to announce percentages + case QAccessible::Role::SpinBox: + return QStringLiteral("android.widget.NumberPicker"); + case QAccessible::Role::WebDocument: + return QStringLiteral("android.webkit.WebView"); + case QAccessible::Role::Dialog: + return QStringLiteral("android.app.AlertDialog"); + case QAccessible::Role::PageTab: + return QStringLiteral("android.app.ActionBar.Tab"); + case QAccessible::Role::PageTabList: + return QStringLiteral("android.widget.TabWidget"); + case QAccessible::Role::ScrollBar: [[fallthrough]]; + case QAccessible::Role::Slider: + return QStringLiteral("android.widget.SeekBar"); + case QAccessible::Role::Table: + // #TODO Evaluate the usage of AccessibleNodeInfo.setCollectionItemInfo() to provide + // infos about colums, rows und items. + return QStringLiteral("android.widget.GridView"); + case QAccessible::Role::Pane: + // #TODO QQuickScrollView, QQuickListView (see QTBUG-137806) + return QStringLiteral("android.view.ViewGroup"); + case QAccessible::Role::AlertMessage: + case QAccessible::Role::Animation: + case QAccessible::Role::Application: + case QAccessible::Role::Assistant: + case QAccessible::Role::BlockQuote: + case QAccessible::Role::Border: + case QAccessible::Role::ButtonDropGrid: + case QAccessible::Role::ButtonDropDown: + case QAccessible::Role::ButtonMenu: + case QAccessible::Role::Canvas: + case QAccessible::Role::Caret: + case QAccessible::Role::Cell: + case QAccessible::Role::Chart: + case QAccessible::Role::Client: + case QAccessible::Role::ColorChooser: + case QAccessible::Role::Column: + case QAccessible::Role::ColumnHeader: + case QAccessible::Role::ComplementaryContent: + case QAccessible::Role::Cursor: + case QAccessible::Role::Desktop: + case QAccessible::Role::Dial: + case QAccessible::Role::Document: + case QAccessible::Role::Equation: + case QAccessible::Role::Footer: + case QAccessible::Role::Form: + case QAccessible::Role::Grip: + case QAccessible::Role::HelpBalloon: + case QAccessible::Role::HotkeyField: + case QAccessible::Role::Indicator: + case QAccessible::Role::LayeredPane: + case QAccessible::Role::ListItem: + case QAccessible::Role::MenuBar: + case QAccessible::Role::NoRole: + case QAccessible::Role::Note: + case QAccessible::Role::Notification: + case QAccessible::Role::Paragraph: + case QAccessible::Role::PropertyPage: + case QAccessible::Role::Row: + case QAccessible::Role::RowHeader: + case QAccessible::Role::Section: + case QAccessible::Role::Sound: + case QAccessible::Role::Splitter: + case QAccessible::Role::StatusBar: + case QAccessible::Role::Terminal: + case QAccessible::Role::TitleBar: + case QAccessible::Role::ToolTip: + case QAccessible::Role::Tree: + case QAccessible::Role::TreeItem: + case QAccessible::Role::UserRole: + case QAccessible::Role::Whitespace: + case QAccessible::Role::Window: + // If unsure, every visible or interactive element in Android + // inherits android.view.View and by many extends also TextView. + // Android itself does a similar thing e.g. in its Settings-App. + return QStringLiteral("android.view.TextView"); + } + } + static QString descriptionForInterface(QAccessibleInterface *iface) { QString desc; @@ -513,6 +638,10 @@ namespace QtAndroidAccessibility return false; } + const QString role = classNameForRole(info.role, info.state); + jstring jrole = env->NewString((jchar*)role.constData(), (jsize)role.size()); + env->CallVoidMethod(node, m_setClassNameMethodID, jrole); + const bool hasClickableAction = info.actions.contains(QAccessibleActionInterface::pressAction()) || info.actions.contains(QAccessibleActionInterface::toggleAction()); @@ -590,6 +719,7 @@ namespace QtAndroidAccessibility } jclass nodeInfoClass = env->FindClass("android/view/accessibility/AccessibilityNodeInfo"); + GET_AND_CHECK_STATIC_METHOD(m_setClassNameMethodID, nodeInfoClass, "setClassName", "(Ljava/lang/CharSequence;)V"); GET_AND_CHECK_STATIC_METHOD(m_addActionMethodID, nodeInfoClass, "addAction", "(I)V"); GET_AND_CHECK_STATIC_METHOD(m_setCheckableMethodID, nodeInfoClass, "setCheckable", "(Z)V"); GET_AND_CHECK_STATIC_METHOD(m_setCheckedMethodID, nodeInfoClass, "setChecked", "(Z)V"); diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 3f40dea5eb9..82e978862f8 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -1662,128 +1662,123 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op } case CE_ItemViewItem: { if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) { - if (qobject_cast<const QAbstractItemView *>(widget)) { - QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); - QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget); - QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); + QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget); + QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget); + QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); - // draw the background - proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget); + // draw the background + proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget); - const QRect &rect = vopt->rect; - const bool isRtl = option->direction == Qt::RightToLeft; - bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne || - vopt->viewItemPosition == QStyleOptionViewItem::Invalid; - bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning; - bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End; + const QRect &rect = vopt->rect; + const bool isRtl = option->direction == Qt::RightToLeft; + bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne || + vopt->viewItemPosition == QStyleOptionViewItem::Invalid; + bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning; + bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End; - // the tree decoration already painted the left side of the rounded rect - if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) && - vopt->showDecorationSelected) { - isFirst = false; - if (onlyOne) { - onlyOne = false; - isLast = true; - } + // the tree decoration already painted the left side of the rounded rect + if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) && + vopt->showDecorationSelected) { + isFirst = false; + if (onlyOne) { + onlyOne = false; + isLast = true; } + } - if (isRtl) { - if (isFirst) { - isFirst = false; - isLast = true; - } else if (isLast) { - isFirst = true; - isLast = false; - } + if (isRtl) { + if (isFirst) { + isFirst = false; + isLast = true; + } else if (isLast) { + isFirst = true; + isLast = false; } - const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver); - if (highlightCurrent) { - const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); - if (highContrastTheme) - painter->setBrush(vopt->palette.highlight()); - else - painter->setBrush(view->alternatingRowColors() ? vopt->palette.highlight() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); - QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr; - if (editorWidget) { - QPalette pal = editorWidget->palette(); - QColor editorBgColor = vopt->backgroundBrush == Qt::NoBrush ? vopt->palette.color(widget->backgroundRole()) : vopt->backgroundBrush.color(); - editorBgColor.setAlpha(255); - pal.setColor(editorWidget->backgroundRole(), editorBgColor); - editorWidget->setPalette(pal); - } - } else { - painter->setBrush(vopt->backgroundBrush); + } + const bool highlightCurrent = vopt->state.testAnyFlags(State_Selected | State_MouseOver); + if (highlightCurrent) { + const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); + if (highContrastTheme) + painter->setBrush(vopt->palette.highlight()); + else + painter->setBrush(view->alternatingRowColors() ? vopt->palette.highlight() : WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); + QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr; + if (editorWidget) { + QPalette pal = editorWidget->palette(); + QColor editorBgColor = vopt->backgroundBrush == Qt::NoBrush ? vopt->palette.color(widget->backgroundRole()) : vopt->backgroundBrush.color(); + editorBgColor.setAlpha(255); + pal.setColor(editorWidget->backgroundRole(), editorBgColor); + editorWidget->setPalette(pal); } - painter->setPen(Qt::NoPen); + } else { + painter->setBrush(vopt->backgroundBrush); + } + painter->setPen(Qt::NoPen); - if (onlyOne) { - painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)), - secondLevelRoundingRadius, secondLevelRoundingRadius); - } else if (isFirst) { - painter->save(); - painter->setClipRect(rect); - painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)), - secondLevelRoundingRadius, secondLevelRoundingRadius); - painter->restore(); - } else if (isLast) { - painter->save(); - painter->setClipRect(rect); - painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)), - secondLevelRoundingRadius, secondLevelRoundingRadius); - painter->restore(); - } else { - painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2))); - } + if (onlyOne) { + painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)), + secondLevelRoundingRadius, secondLevelRoundingRadius); + } else if (isFirst) { + painter->save(); + painter->setClipRect(rect); + painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)), + secondLevelRoundingRadius, secondLevelRoundingRadius); + painter->restore(); + } else if (isLast) { + painter->save(); + painter->setClipRect(rect); + painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)), + secondLevelRoundingRadius, secondLevelRoundingRadius); + painter->restore(); + } else { + painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2))); + } - // draw the check mark - if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) { - QStyleOptionViewItem option(*vopt); - option.rect = checkRect; - option.state = option.state & ~QStyle::State_HasFocus; + // draw the check mark + if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) { + QStyleOptionViewItem option(*vopt); + option.rect = checkRect; + option.state = option.state & ~QStyle::State_HasFocus; - switch (vopt->checkState) { - case Qt::Unchecked: - option.state |= QStyle::State_Off; - break; - case Qt::PartiallyChecked: - option.state |= QStyle::State_NoChange; - break; - case Qt::Checked: - option.state |= QStyle::State_On; - break; - } - proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget); + switch (vopt->checkState) { + case Qt::Unchecked: + option.state |= QStyle::State_Off; + break; + case Qt::PartiallyChecked: + option.state |= QStyle::State_NoChange; + break; + case Qt::Checked: + option.state |= QStyle::State_On; + break; } + proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget); + } - // draw the icon - QIcon::Mode mode = QIcon::Normal; - if (!(vopt->state & QStyle::State_Enabled)) - mode = QIcon::Disabled; - else if (vopt->state & QStyle::State_Selected) - mode = QIcon::Selected; - QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; - vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state); - - painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color() - : vopt->palette.text().color()); - d->viewItemDrawText(painter, vopt, textRect); - - // paint a vertical marker for QListView - if (vopt->state & State_Selected) { - if (const QListView *lv = qobject_cast<const QListView *>(widget); - lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) { - painter->setPen(vopt->palette.accent().color()); - const auto xPos = isRtl ? rect.right() - 1 : rect.left(); - const QLineF lines[2] = { - QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2), - QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2), - }; - painter->drawLines(lines, 2); - } + // draw the icon + QIcon::Mode mode = QIcon::Normal; + if (!(vopt->state & QStyle::State_Enabled)) + mode = QIcon::Disabled; + else if (vopt->state & QStyle::State_Selected) + mode = QIcon::Selected; + QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off; + vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state); + + painter->setPen(highlightCurrent && highContrastTheme ? vopt->palette.base().color() + : vopt->palette.text().color()); + d->viewItemDrawText(painter, vopt, textRect); + + // paint a vertical marker for QListView + if (vopt->state & State_Selected) { + if (const QListView *lv = qobject_cast<const QListView *>(widget); + lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) { + painter->setPen(vopt->palette.accent().color()); + const auto xPos = isRtl ? rect.right() - 1 : rect.left(); + const QLineF lines[2] = { + QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2), + QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2), + }; + painter->drawLines(lines, 2); } - } else { - QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget); - d->viewItemDrawText(painter, vopt, textRect); } } break; |