From f172435724ca0c4ccc61716776ca7405a731c547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20J=C3=B6rgensen?= Date: Tue, 17 Mar 2026 17:56:12 +0100 Subject: [PATCH] Accessibility fixs: * Fix focus and screen reader on Dialog #LINQT-2197 * Fix dialer accessibility #LINQT-2204 * Add accessibility to voicemail button #LINQT-2200 *Add list annoncement on magicsearch suggestions #LINQT-2205 * Fix accessibility on contact lists #LINQT-2206 * Fix screen reader does not say values on combobox #LINQT-2195 * Fix focus when close modal #LINQT-2220 * Focus end call button when accepting a call #LINQT-2223 --- Linphone/tool/ui/FocusNavigator.cpp | 11 +++- Linphone/tool/ui/FocusNavigator.hpp | 4 ++ Linphone/view/Control/Button/ComboBox.qml | 24 ++++++++- .../Display/Contact/ContactListItem.qml | 1 + .../Display/Contact/ContactListView.qml | 3 ++ .../Control/Display/Contact/Voicemail.qml | 13 +++-- .../Form/Settings/MultimediaSettings.qml | 8 +-- Linphone/view/Control/Input/NumericPad.qml | 22 ++++---- Linphone/view/Control/Popup/Dialog/Dialog.qml | 33 +++++++++++- .../view/Control/Popup/NumericPadPopup.qml | 52 +++++++++---------- .../view/Page/Form/Login/SIPLoginPage.qml | 2 +- .../view/Page/Form/Meeting/MeetingForm.qml | 8 +++ .../view/Page/Form/Register/RegisterPage.qml | 2 +- Linphone/view/Page/Layout/Main/MainLayout.qml | 23 ++++++-- .../Settings/AccountSettingsGeneralLayout.qml | 1 + .../Settings/AdvancedSettingsLayout.qml | 2 +- .../Settings/CallForwardSettingsLayout.qml | 2 +- .../Settings/MeetingsSettingsLayout.qml | 1 + Linphone/view/Page/Main/Call/CallPage.qml | 6 ++- .../view/Page/Main/Contact/ContactPage.qml | 12 ++++- .../view/Page/Window/Call/CallsWindow.qml | 10 +--- 21 files changed, 166 insertions(+), 74 deletions(-) diff --git a/Linphone/tool/ui/FocusNavigator.cpp b/Linphone/tool/ui/FocusNavigator.cpp index e94724b70..132aef40a 100644 --- a/Linphone/tool/ui/FocusNavigator.cpp +++ b/Linphone/tool/ui/FocusNavigator.cpp @@ -32,12 +32,17 @@ bool FocusNavigator::doesLastFocusWasKeyboard() { return mLastFocusWasKeyboard; } -bool FocusNavigator::eventFilter(QObject *, QEvent *event) { +QQuickItem *FocusNavigator::getLastFocusItem() { + return mLastFocusItem; +} + +bool FocusNavigator::eventFilter(QObject *obj, QEvent *event) { switch (event->type()) { case QEvent::FocusIn: { auto fe = static_cast(event); if (fe) { int focusReason = fe->reason(); + // qDebug() << "New focus object" << obj << "| reason" << focusReason; mLastFocusWasKeyboard = (focusReason == Qt::TabFocusReason || focusReason == Qt::BacktabFocusReason); } break; @@ -45,12 +50,14 @@ bool FocusNavigator::eventFilter(QObject *, QEvent *event) { default: break; } - return false; + return QObject::eventFilter(obj, event); } void FocusNavigator::onFocusObjectChanged(QObject *obj) { // qDebug() << "New focus object" << obj; // Usefull to debug focus problems auto item = qobject_cast(obj); + mLastFocusItem = item; if (!item) return; emit focusChanged(item, mLastFocusWasKeyboard); + emit lastFocusItemChanged(); } diff --git a/Linphone/tool/ui/FocusNavigator.hpp b/Linphone/tool/ui/FocusNavigator.hpp index 955cf743e..5df2df291 100644 --- a/Linphone/tool/ui/FocusNavigator.hpp +++ b/Linphone/tool/ui/FocusNavigator.hpp @@ -25,18 +25,22 @@ class FocusNavigator : public QObject { Q_OBJECT + Q_PROPERTY(QQuickItem* lastFocusItem READ getLastFocusItem NOTIFY lastFocusItemChanged) public: explicit FocusNavigator(QObject *parent = nullptr); Q_INVOKABLE bool doesLastFocusWasKeyboard(); + Q_INVOKABLE QQuickItem *getLastFocusItem(); protected: bool eventFilter(QObject *obj, QEvent *event) override; signals: void focusChanged(QQuickItem *item, bool keyboardFocus); + void lastFocusItemChanged(); private: bool mLastFocusWasKeyboard = false; + QQuickItem *mLastFocusItem = nullptr; void onFocusObjectChanged(QObject *obj); }; diff --git a/Linphone/view/Control/Button/ComboBox.qml b/Linphone/view/Control/Button/ComboBox.qml index 5175ffc3d..5d9b004fb 100644 --- a/Linphone/view/Control/Button/ComboBox.qml +++ b/Linphone/view/Control/Button/ComboBox.qml @@ -38,6 +38,18 @@ Control.ComboBox { property color color: DefaultStyle.grey_100 property color disabledColor: DefaultStyle.grey_200 + // Accessibility properties + property string accessibleLabel: "" + Accessible.name: generateAccessibleName() + + function generateAccessibleName() { + return currentText ? + //: %1 actual value %2 + qsTr("combobox_with_value_accessible_name").arg(accessibleLabel).arg(currentText) : + accessibleLabel + + } + onConstantImageSourceChanged: if (constantImageSource) selectedItemImg.imageSource = constantImageSource onCurrentIndexChanged: { @@ -52,6 +64,12 @@ Control.ComboBox { selectedItemImg.imageSource = constantImageSource ? constantImageSource : item.img ? item.img : ""; } + // Used for accessibility, contentItem remove value announcement from screen reader + onCurrentTextChanged: { + Accessible.name = generateAccessibleName() + Accessible.announce(currentText) + } + Keys.onPressed: event => { if (!mainItem.contentItem.activeFocus && (event.key == Qt.Key_Space || event.key == Qt.Key_Enter || event.key == Qt.Key_Return)) { mainItem.popup.open(); @@ -181,11 +199,13 @@ Control.ComboBox { } delegate: Item { + id: delegate width: mainItem.width height: mainItem.height // anchors.left: listView.left // anchors.right: listView.right - Accessible.name: typeof (modelData) != "undefined" ? mainItem.textRole ? modelData[mainItem.textRole] : modelData.text ? modelData.text : modelData : $modelData ? mainItem.textRole ? $modelData[mainItem.textRole] : $modelData : "" + property string valueText: typeof (modelData) != "undefined" ? mainItem.textRole ? modelData[mainItem.textRole] : modelData.text ? modelData.text : modelData : $modelData ? mainItem.textRole ? $modelData[mainItem.textRole] : $modelData : "" + Accessible.name: valueText RowLayout { anchors.fill: parent EffectImage { @@ -216,7 +236,7 @@ Control.ComboBox { Layout.leftMargin: delegateImg.visible ? 0 : Utils.getSizeWithScreenRatio(flagItem.visble ? 5 : 25) Layout.rightMargin: Utils.getSizeWithScreenRatio(20) Layout.alignment: Qt.AlignCenter - text: typeof (modelData) != "undefined" ? mainItem.textRole ? modelData[mainItem.textRole] : modelData.text ? modelData.text : modelData : $modelData ? mainItem.textRole ? $modelData[mainItem.textRole] : $modelData : "" + text: delegate.valueText elide: Text.ElideRight maximumLineCount: 1 wrapMode: Text.WrapAnywhere diff --git a/Linphone/view/Control/Display/Contact/ContactListItem.qml b/Linphone/view/Control/Display/Contact/ContactListItem.qml index f8155d148..c4595e2d0 100644 --- a/Linphone/view/Control/Display/Contact/ContactListItem.qml +++ b/Linphone/view/Control/Display/Contact/ContactListItem.qml @@ -43,6 +43,7 @@ FocusScope { signal contactDeletionRequested(FriendGui contact) signal containsMouseChanged(bool containsMouse) Accessible.name: displayName + Accessible.role: Accessible.ListItem MouseArea { Text { diff --git a/Linphone/view/Control/Display/Contact/ContactListView.qml b/Linphone/view/Control/Display/Contact/ContactListView.qml index d5944d301..05941d2a1 100644 --- a/Linphone/view/Control/Display/Contact/ContactListView.qml +++ b/Linphone/view/Control/Display/Contact/ContactListView.qml @@ -61,6 +61,9 @@ ListView { onVisibleChanged: if (visible && !expanded) expanded = true onYChanged: updatePosition() + + Accessible.role: Accessible.List + Accessible.name: title // Qt bug: sometimes, containsMouse may not be send and update on each MouseArea. // So we need to use this variable to switch off all hovered items. diff --git a/Linphone/view/Control/Display/Contact/Voicemail.qml b/Linphone/view/Control/Display/Contact/Voicemail.qml index aba4fe242..cc2f6bfbc 100644 --- a/Linphone/view/Control/Display/Contact/Voicemail.qml +++ b/Linphone/view/Control/Display/Contact/Voicemail.qml @@ -5,30 +5,29 @@ import QtQuick.Controls.Basic import Linphone import UtilsCpp import SettingsCpp +import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils Rectangle{ id: mainItem property int voicemailCount: 0 property bool showMwi: false + property real scaleFactor: 1.0 width: Utils.getSizeWithScreenRatio(42 * scaleFactor) height: Utils.getSizeWithScreenRatio(36 * scaleFactor) - property real scaleFactor: 1.0 signal clicked() color: 'transparent' - Button { + IconButton { anchors.bottom: parent.bottom anchors.left: parent.left + style: ButtonStyle.noBackground icon.source: AppIcons.voicemail - icon.color: DefaultStyle.main2_600 width: Utils.getSizeWithScreenRatio(33 * scaleFactor) height: width icon.width: width icon.height: width - padding: 0 - background: Item { - anchors.fill: parent - } + //: "Voicemail" + Accessible.name: qsTr("voicemail_accessible_name") onClicked: { mainItem.clicked() } diff --git a/Linphone/view/Control/Form/Settings/MultimediaSettings.qml b/Linphone/view/Control/Form/Settings/MultimediaSettings.qml index e81d9d2c5..361473edf 100644 --- a/Linphone/view/Control/Form/Settings/MultimediaSettings.qml +++ b/Linphone/view/Control/Form/Settings/MultimediaSettings.qml @@ -57,7 +57,7 @@ ColumnLayout { propertyOwner: SettingsCpp textRole: 'display_name' //: Choose %1 - Accessible.name: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_ringer_title")) + accessibleLabel: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_ringer_title")) } Item { Layout.fillHeight: true @@ -98,7 +98,7 @@ ColumnLayout { SettingsCpp.lSetPlaybackDevice(outputAudioDeviceCBox.currentValue) } } - Accessible.name: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_speaker_title")) + accessibleLabel: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_speaker_title")) } Slider { id: speakerVolume @@ -149,7 +149,7 @@ ColumnLayout { SettingsCpp.lSetCaptureDevice(inputAudioDeviceCBox.currentValue) } } - Accessible.name: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_microphone_title")) + accessibleLabel: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_microphone_title")) } Slider { id: microVolume @@ -238,7 +238,7 @@ ColumnLayout { SettingsCpp.lSetVideoDevice(videoDevicesCbox.currentValue) } } - Accessible.name: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_camera_title")) + accessibleLabel: qsTr("choose_something_accessible_name").arg(qsTr("multimedia_settings_camera_title")) } } Connections { diff --git a/Linphone/view/Control/Input/NumericPad.qml b/Linphone/view/Control/Input/NumericPad.qml index c5fb1b5dc..80638d035 100644 --- a/Linphone/view/Control/Input/NumericPad.qml +++ b/Linphone/view/Control/Input/NumericPad.qml @@ -1,6 +1,6 @@ import QtQuick import QtQuick.Controls.Basic as Control -import QtQuick.Layouts as Layout +import QtQuick.Layouts import QtQuick.Effects import Linphone import UtilsCpp @@ -107,11 +107,12 @@ FocusScope { } } - Layout.GridLayout { + GridLayout { id: numPadGrid columns: 3 columnSpacing: Utils.getSizeWithScreenRatio(40) rowSpacing: Utils.getSizeWithScreenRatio(10) + function getButtonAt(index){ index = (index+15) % 15 if(index >= 0){ @@ -131,7 +132,7 @@ FocusScope { model: 9 BigButton { id: numPadButton - Layout.Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignHCenter required property int index implicitWidth: Utils.getSizeWithScreenRatio(60) implicitHeight: Utils.getSizeWithScreenRatio(60) @@ -158,7 +159,7 @@ FocusScope { ] BigButton { id: digitButton - Layout.Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignHCenter implicitWidth: Utils.getSizeWithScreenRatio(60) implicitHeight: Utils.getSizeWithScreenRatio(60) @@ -212,7 +213,7 @@ FocusScope { visible: mainItem.lastRowVisible implicitWidth: Utils.getSizeWithScreenRatio(75) implicitHeight: Utils.getSizeWithScreenRatio(55) - Layout.Layout.alignment: Qt.AlignHCenter + Layout.alignment: Qt.AlignHCenter icon.width: Utils.getSizeWithScreenRatio(32) icon.height: Utils.getSizeWithScreenRatio(32) radius: Utils.getSizeWithScreenRatio(71) @@ -231,17 +232,14 @@ FocusScope { Button { id: eraseButton visible: mainItem.lastRowVisible - leftPadding: Utils.getSizeWithScreenRatio(5) - rightPadding: Utils.getSizeWithScreenRatio(5) - topPadding: Utils.getSizeWithScreenRatio(5) - bottomPadding: Utils.getSizeWithScreenRatio(5) - Layout.Layout.alignment: Qt.AlignHCenter + padding: Utils.getSizeWithScreenRatio(5) + Layout.alignment: Qt.AlignHCenter icon.source: AppIcons.backspaceFill style: ButtonStyle.noBackground icon.width: Utils.getSizeWithScreenRatio(38) icon.height: Utils.getSizeWithScreenRatio(38) - Layout.Layout.preferredWidth: Utils.getSizeWithScreenRatio(38) - Layout.Layout.preferredHeight: Utils.getSizeWithScreenRatio(38) + Layout.preferredWidth: Utils.getSizeWithScreenRatio(38) + Layout.preferredHeight: Utils.getSizeWithScreenRatio(38) //: Erase Accessible.name: qsTr("erase_accessible_name") diff --git a/Linphone/view/Control/Popup/Dialog/Dialog.qml b/Linphone/view/Control/Popup/Dialog/Dialog.qml index d3a9a62f1..1110f1291 100644 --- a/Linphone/view/Control/Popup/Dialog/Dialog.qml +++ b/Linphone/view/Control/Popup/Dialog/Dialog.qml @@ -37,13 +37,38 @@ Popup { signal accepted() signal rejected() + property Item itemToFocusOnClose: null + property bool quitWithKeyboard : false + + function updateQuitWithKeyboardPress (event) { + if(visible && (event.key == Qt.Key_Escape || event.key == Qt.Key_Enter || event.key == Qt.Key_Space || event.key == Qt.Key_Return)){ + mainItem.quitWithKeyboard = true + } + } + + onAboutToHide: { + if(mainItem.itemToFocusOnClose && mainItem.itemToFocusOnClose.visible && mainItem.quitWithKeyboard){ + // Focus last element that was focused before Dialog was opened + mainItem.itemToFocusOnClose.forceActiveFocus(Qt.TabFocusReason) + } + mainItem.itemToFocusOnClose = null + } + contentItem: FocusScope { + Accessible.role: Accessible.Dialog + Accessible.name: mainItem.title + Accessible.description: mainItem.details implicitWidth: child.implicitWidth implicitHeight: child.implicitHeight onVisibleChanged: { - if(visible) forceActiveFocus() + if(visible){ + mainItem.itemToFocusOnClose = FocusNavigator.lastFocusItem + const focusReason = FocusNavigator.doesLastFocusWasKeyboard() ? Qt.TabFocusReason : Qt.OtherFocusReason + forceActiveFocus(focusReason) + } } Keys.onPressed: (event) => { + mainItem.updateQuitWithKeyboardPress(event) if(visible && event.key == Qt.Key_Escape){ mainItem.close() event.accepted = true @@ -129,6 +154,9 @@ Popup { mainItem.rejected() mainItem.close() } + Keys.onPressed: (event) => { + mainItem.updateQuitWithKeyboardPress(event) + } KeyNavigation.left: secondButtonId KeyNavigation.right: secondButtonId } @@ -145,6 +173,9 @@ Popup { mainItem.rejected() mainItem.close() } + Keys.onPressed: (event) => { + mainItem.updateQuitWithKeyboardPress(event) + } KeyNavigation.left: firstButtonId KeyNavigation.right: firstButtonId } diff --git a/Linphone/view/Control/Popup/NumericPadPopup.qml b/Linphone/view/Control/Popup/NumericPadPopup.qml index 529448e99..01fc02a40 100644 --- a/Linphone/view/Control/Popup/NumericPadPopup.qml +++ b/Linphone/view/Control/Popup/NumericPadPopup.qml @@ -1,6 +1,6 @@ import QtQuick import QtQuick.Controls.Basic as Control -import QtQuick.Layouts as Layout +import QtQuick.Layouts import QtQuick.Effects import Linphone import UtilsCpp @@ -10,15 +10,16 @@ import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils Control.Popup { id: mainItem closePolicy: Control.Popup.CloseOnEscape - leftPadding: Utils.getSizeWithScreenRatio(72) - rightPadding: Utils.getSizeWithScreenRatio(72) - topPadding: Utils.getSizeWithScreenRatio(41) - bottomPadding: Utils.getSizeWithScreenRatio(18) + padding: Utils.getSizeWithScreenRatio(10) property bool closeButtonVisible: true property bool roundedBottom: false property bool lastRowVisible: true property var currentCall - onOpened: numPad.forceActiveFocus() + focus: true + onOpened: { + const focusReason = FocusNavigator.doesLastFocusWasKeyboard() ? Qt.TabFocusReason : Qt.OtherFocusReason + numPad.forceActiveFocus(focusReason) + } signal buttonPressed(string text) signal keyPadKeyPressed(KeyEvent event) onKeyPadKeyPressed: (event) => { @@ -35,6 +36,8 @@ Control.Popup { height: parent.height color: DefaultStyle.grey_100 radius: Utils.getSizeWithScreenRatio(20) + bottomLeftRadius: mainItem.roundedBottom ? radius : 0 + bottomRightRadius: mainItem.roundedBottom ? radius : 0 } MultiEffect { id: effect @@ -46,24 +49,19 @@ Control.Popup { shadowBlur: 0.1 z: -1 } - Rectangle { - width: parent.width - height: parent.height / 2 - anchors.bottom: parent.bottom - color: DefaultStyle.grey_100 - visible: !mainItem.roundedBottom - } MouseArea { anchors.fill: parent onClicked: numPad.forceActiveFocus() } + } + contentItem: ColumnLayout{ + Accessible.role: Accessible.Dialog + //: "Numeric Pad" + Accessible.name : qsTr("numeric_pad_accessible_name") BigButton { id: closeButton visible: mainItem.closeButtonVisible - anchors.top: parent.top - anchors.right: parent.right - anchors.topMargin: Utils.getSizeWithScreenRatio(10) - anchors.rightMargin: Utils.getSizeWithScreenRatio(10) + Layout.alignment: Qt.AlignRight icon.source: AppIcons.closeX icon.width: Utils.getSizeWithScreenRatio(24) icon.height: Utils.getSizeWithScreenRatio(24) @@ -72,15 +70,17 @@ Control.Popup { //: Close numeric pad Accessible.name: qsTr("close_numeric_pad_accessible_name") } - } - contentItem: NumericPad{ - id: numPad - lastRowVisible: mainItem.lastRowVisible - currentCall: mainItem.currentCall - onButtonPressed: (text) => { - mainItem.buttonPressed(text) + NumericPad{ + id: numPad + Layout.alignment: Qt.AlignCenter + Layout.bottomMargin: Utils.getSizeWithScreenRatio(5) + lastRowVisible: mainItem.lastRowVisible + currentCall: mainItem.currentCall + onButtonPressed: (text) => { + mainItem.buttonPressed(text) + } + onLaunchCall: mainItem.launchCall() + onWipe: mainItem.wipe() } - onLaunchCall: mainItem.launchCall() - onWipe: mainItem.wipe() } } diff --git a/Linphone/view/Page/Form/Login/SIPLoginPage.qml b/Linphone/view/Page/Form/Login/SIPLoginPage.qml index 54d8d82ed..e265fb0b0 100644 --- a/Linphone/view/Page/Form/Login/SIPLoginPage.qml +++ b/Linphone/view/Page/Form/Login/SIPLoginPage.qml @@ -276,7 +276,7 @@ LoginLayout { }) KeyNavigation.up: displayName KeyNavigation.down: outboundProxyUriEdit - Accessible.name: qsTr("transport") + accessibleLabel: qsTr("transport") } } } diff --git a/Linphone/view/Page/Form/Meeting/MeetingForm.qml b/Linphone/view/Page/Form/Meeting/MeetingForm.qml index 217ae65b0..2a6bfc8c1 100644 --- a/Linphone/view/Page/Form/Meeting/MeetingForm.qml +++ b/Linphone/view/Page/Form/Meeting/MeetingForm.qml @@ -120,6 +120,8 @@ FocusScope { startHour.selectedDateTime = UtilsCpp.createDateTime(selectedDate, startHour.selectedHour, startHour.selectedMin) endHour.selectedDateTime = UtilsCpp.createDateTime(selectedDate, endHour.selectedHour, endHour.selectedMin) } + //: Day + accessibleLabel: qsTr("day_accessible_name") } }, RowLayout { @@ -147,6 +149,8 @@ FocusScope { endHour.selectedDateTime = UtilsCpp.addSecs(selectedDateTime, 3600) } } + //: Start time + accessibleLabel: qsTr("start_time_accessible_name") } TimeComboBox { id: endHour @@ -160,6 +164,8 @@ FocusScope { KeyNavigation.down: timeZoneCbox KeyNavigation.left: startHour KeyNavigation.right: startHour + //: End time + accessibleLabel: qsTr("end_time_accessible_name") } Item { Layout.fillWidth: true @@ -200,6 +206,8 @@ FocusScope { var modelIndex = timeZoneCbox.model.index(currentIndex, 0) mainItem.conferenceInfoGui.core.timeZoneModel = timeZoneCbox.model.data(modelIndex, Qt.DisplayRole + 1) } + //: Timezone + accessibleLabel: qsTr("timezone_accessible_name") } ] diff --git a/Linphone/view/Page/Form/Register/RegisterPage.qml b/Linphone/view/Page/Form/Register/RegisterPage.qml index 9b83cc7da..c79ece1fc 100644 --- a/Linphone/view/Page/Form/Register/RegisterPage.qml +++ b/Linphone/view/Page/Form/Register/RegisterPage.qml @@ -155,7 +155,7 @@ LoginLayout { Layout.preferredHeight: Utils.getSizeWithScreenRatio(49) enabled: false model: [{text:"@sip.linphone.org"}] - Accessible.name: qsTr("domain") + accessibleLabel: qsTr("domain") } EffectImage { Layout.preferredWidth: Utils.getSizeWithScreenRatio(16) diff --git a/Linphone/view/Page/Layout/Main/MainLayout.qml b/Linphone/view/Page/Layout/Main/MainLayout.qml index bdc9508f4..bb0e591d8 100644 --- a/Linphone/view/Page/Layout/Main/MainLayout.qml +++ b/Linphone/view/Page/Layout/Main/MainLayout.qml @@ -314,6 +314,8 @@ Item { sectionsSpacing: Utils.getSizeWithScreenRatio(5) searchBarText: magicSearchBar.text + //: "Searchbar suggestions" + Accessible.name: qsTr("searchbar_suggestions_accessible_name") } } } @@ -724,7 +726,12 @@ Item { Component { id: accountSettingsPageComponent AccountSettingsPage { - onGoBack: closeContextualMenuComponent() + onGoBack: { + closeContextualMenuComponent() + if(FocusNavigator.doesLastFocusWasKeyboard()){ + mainItem.nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason) + } + } onAccountRemoved: { closeContextualMenuComponent(); mainItem.accountRemoved(); @@ -734,13 +741,23 @@ Item { Component { id: settingsPageComponent SettingsPage { - onGoBack: closeContextualMenuComponent() + onGoBack: { + closeContextualMenuComponent() + if(FocusNavigator.doesLastFocusWasKeyboard()){ + mainItem.nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason) + } + } } } Component { id: helpPageComponent HelpPage { - onGoBack: closeContextualMenuComponent() + onGoBack: { + closeContextualMenuComponent() + if(FocusNavigator.doesLastFocusWasKeyboard()){ + mainItem.nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason) + } + } } } Control.StackView { diff --git a/Linphone/view/Page/Layout/Settings/AccountSettingsGeneralLayout.qml b/Linphone/view/Page/Layout/Settings/AccountSettingsGeneralLayout.qml index 7e36fddd0..0c02e5c79 100644 --- a/Linphone/view/Page/Layout/Settings/AccountSettingsGeneralLayout.qml +++ b/Linphone/view/Page/Layout/Settings/AccountSettingsGeneralLayout.qml @@ -176,6 +176,7 @@ AbstractSettingsLayout { propertyOwnerGui: account textRole: 'text' flagRole: 'flag' + accessibleLabel: qsTr("manage_account_international_prefix") } SwitchSetting { titleText: account?.core.humaneReadableRegistrationState diff --git a/Linphone/view/Page/Layout/Settings/AdvancedSettingsLayout.qml b/Linphone/view/Page/Layout/Settings/AdvancedSettingsLayout.qml index 8d6a3aa87..4d0ffcf1d 100644 --- a/Linphone/view/Page/Layout/Settings/AdvancedSettingsLayout.qml +++ b/Linphone/view/Page/Layout/Settings/AdvancedSettingsLayout.qml @@ -125,7 +125,7 @@ AbstractSettingsLayout { propertyName: "mediaEncryption" textRole: 'display_name' propertyOwner: SettingsCpp - Accessible.name: qsTr("settings_advanced_media_encryption_title") + accessibleLabel: qsTr("settings_advanced_media_encryption_title") } } SwitchSetting { diff --git a/Linphone/view/Page/Layout/Settings/CallForwardSettingsLayout.qml b/Linphone/view/Page/Layout/Settings/CallForwardSettingsLayout.qml index 1b1ef1139..541905d16 100644 --- a/Linphone/view/Page/Layout/Settings/CallForwardSettingsLayout.qml +++ b/Linphone/view/Page/Layout/Settings/CallForwardSettingsLayout.qml @@ -94,7 +94,7 @@ AbstractSettingsLayout { SettingsCpp.callForwardToAddress = "voicemail"; } } - + accessibleLabel: qsTr("settings_call_forward_destination_choose") } DecoratedTextField { id: sipInputField diff --git a/Linphone/view/Page/Layout/Settings/MeetingsSettingsLayout.qml b/Linphone/view/Page/Layout/Settings/MeetingsSettingsLayout.qml index 83d07327e..5c2ef0bdb 100644 --- a/Linphone/view/Page/Layout/Settings/MeetingsSettingsLayout.qml +++ b/Linphone/view/Page/Layout/Settings/MeetingsSettingsLayout.qml @@ -55,6 +55,7 @@ AbstractSettingsLayout { propertyName: "conferenceLayout" propertyOwner: SettingsCpp textRole: 'display_name' + accessibleLabel: qsTr("settings_meetings_default_layout_title") } } SwitchSetting { diff --git a/Linphone/view/Page/Main/Call/CallPage.qml b/Linphone/view/Page/Main/Call/CallPage.qml index e54f229a0..fcc001c67 100644 --- a/Linphone/view/Page/Main/Call/CallPage.qml +++ b/Linphone/view/Page/Main/Call/CallPage.qml @@ -337,7 +337,10 @@ AbstractMainPage { width: parent?.width height: parent?.height Control.StackView.onActivated: { - callContactsList.forceActiveFocus() + if(!numericPadPopupItem.visible){ + const focusReason = FocusNavigator.doesLastFocusWasKeyboard() ? Qt.TabFocusReason : Qt.OtherFocusReason + callContactsList.forceActiveFocus(focusReason) + } } ColumnLayout { anchors.fill: parent @@ -379,7 +382,6 @@ AbstractMainPage { Layout.topMargin: Utils.getSizeWithScreenRatio(18) Layout.fillWidth: true Layout.fillHeight: true - focus: true numPadPopup: numericPadPopupItem searchBarColor: DefaultStyle.grey_100 onContactClicked: contact => { diff --git a/Linphone/view/Page/Main/Contact/ContactPage.qml b/Linphone/view/Page/Main/Contact/ContactPage.qml index 082f2c4e7..d18d8674d 100644 --- a/Linphone/view/Page/Main/Contact/ContactPage.qml +++ b/Linphone/view/Page/Main/Contact/ContactPage.qml @@ -42,7 +42,7 @@ AbstractMainPage { rightPanelStackView.clear() contactList.resetSelections() } - function goToContactDetails() { + function goToContactDetails(focusEditButton=false) { if (selectedContact) { var firstItem = rightPanelStackView.get(0) if (firstItem && firstItem.objectName == "contactDetail") @@ -58,6 +58,10 @@ AbstractMainPage { rightPanelStackView.push(contactDetail) } } + if(focusEditButton){ + rightPanelStackView.get(0).focusEditButton() + } + } else { rightPanelStackView.clear() } @@ -335,6 +339,10 @@ AbstractMainPage { width: parent?.width height: parent?.height property string objectName: "contactDetail" + + function focusEditButton(){ + contactDetail.button.forceActiveFocus(Qt.TabFocusReason) + } component ContactDetailLayout: ColumnLayout { id: contactDetailLayout spacing: Utils.getSizeWithScreenRatio(15) @@ -922,7 +930,7 @@ AbstractMainPage { ContactEdition { property string objectName: "contactEdition" onCloseEdition: redirectAddress => { - goToContactDetails() + goToContactDetails(true) if (redirectAddress) { initialFriendToDisplay = redirectAddress } diff --git a/Linphone/view/Page/Window/Call/CallsWindow.qml b/Linphone/view/Page/Window/Call/CallsWindow.qml index 0acfca7e8..083a4f26f 100644 --- a/Linphone/view/Page/Window/Call/CallsWindow.qml +++ b/Linphone/view/Page/Window/Call/CallsWindow.qml @@ -333,7 +333,6 @@ AbstractWindow { Rectangle { anchors.fill: parent color: DefaultStyle.grey_900 - focus: true ColumnLayout { anchors.fill: parent @@ -865,10 +864,6 @@ AbstractWindow { roundedBottom: true lastRowVisible: false visible: false - leftPadding: Utils.getSizeWithScreenRatio(40) - rightPadding: Utils.getSizeWithScreenRatio(40) - topPadding: Utils.getSizeWithScreenRatio(41) - bottomPadding: Utils.getSizeWithScreenRatio(18) Component.onCompleted: parent.height = height } } @@ -904,10 +899,6 @@ AbstractWindow { parent: numericPadContainer roundedBottom: true visible: newCallForm.searchBar.numericPadButton.checked - leftPadding: Utils.getSizeWithScreenRatio(40) - rightPadding: Utils.getSizeWithScreenRatio(40) - topPadding: Utils.getSizeWithScreenRatio(41) - bottomPadding: Utils.getSizeWithScreenRatio(18) onLaunchCall: { rightPanel.visible = false UtilsCpp.createCall(newCallForm.searchBar.text) @@ -1407,6 +1398,7 @@ AbstractWindow { // End call button BigButton { id: endCallButton + focus: true Layout.row: 0 icon.width: Utils.getSizeWithScreenRatio(32) icon.height: Utils.getSizeWithScreenRatio(32)