Skip to content

Commit

Permalink
[keyboard-alt]: Announce state changes to connected devices
Browse files Browse the repository at this point in the history
Bug: b/279503977
Change-Id: I7e23daa39fe1f91023d3260df1e6dc46bb47f2e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4779641
Reviewed-by: Wes Okuhara <wesokuhara@google.com>
Commit-Queue: Michael Checo <michaelcheco@google.com>
Reviewed-by: David Padlipsky <dpad@google.com>
Cr-Commit-Position: refs/heads/main@{#1185303}
  • Loading branch information
Michael Checo authored and Chromium LUCI CQ committed Aug 18, 2023
1 parent 8eaed64 commit bb966d0
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 11 deletions.
15 changes: 15 additions & 0 deletions chrome/app/os_settings_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -5422,6 +5422,21 @@ Press an assigned switch or key to remove assignment.
<message name="IDS_SETTINGS_PER_DEVICE_KEYBOARD_KEY_DISABLED" desc="In keyboard remap keys subpage, the dropdown list item for a disabled key.">
disabled
</message>
<message name="IDS_SETTINGS_PER_DEVICE_CONNECTED_A11Y_LABEL" desc="The message announced to screen readers when a device is connected.">
<ph name="DEVICE_NAME">$1<ex>Internal Keyboard</ex></ph> has been connected
</message>
<message name="IDS_SETTINGS_PER_DEVICE_DISCONNECTED_A11Y_LABEL" desc="The message announced to screen readers when a device is disconnected.">
<ph name="DEVICE_NAME">$1<ex>Internal Keyboard</ex></ph> has been disconnected
</message>
<message name="IDS_SETTINGS_PER_DEVICE_ALL_MICE_DISCONNECTED_A11Y_LABEL" desc="The message announced to screen readers when all mice have been disconnected.">
All mice have been disconnected
</message>
<message name="IDS_SETTINGS_PER_DEVICE_ALL_TOUCHPADS_DISCONNECTED_A11Y_LABEL" desc="The message announced to screen readers when all mice have been disconnected.">
All touchpads have been disconnected
</message>
<message name="IDS_SETTINGS_PER_DEVICE_ALL_POINTING_STICKS_DISCONNECTED_A11Y_LABEL" desc="The message announced to screen readers when all mice have been disconnected.">
All TrackPoints have been disconnected
</message>

<!-- Device Keyboard page (OS settings) -->
<message name="IDS_SETTINGS_KEYBOARD_TITLE" desc="In Device Settings, the title of the keyboard settings subpage.">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e049e24d929253189dcd02d6cd5f18e887a8040b
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d6ed8ef0df412df85d44998f0b3b1ec14d58dc03
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d6ed8ef0df412df85d44998f0b3b1ec14d58dc03
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4ec1e53325cbdf5a29eb3bd6f28632987b7b2240
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4ec1e53325cbdf5a29eb3bd6f28632987b7b2240
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import '../os_settings_page/os_settings_subpage.js';
import '../os_settings_page/settings_card.js';
import '../settings_shared.css.js';

import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {CrLinkRowElement} from 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
Expand Down Expand Up @@ -494,13 +495,18 @@ class SettingsDevicePageElement extends SettingsDevicePageElementBase {
private mouseChanged_() {
if ((!this.mice || this.mice.length === 0) &&
Router.getInstance().currentRoute === routes.PER_DEVICE_MOUSE) {
getAnnouncerInstance().announce(
this.i18n('allMiceDisconnectedA11yLabel'));
Router.getInstance().navigateTo(routes.DEVICE);
}
}

private touchpadChanged_() {
if ((!this.touchpads || this.touchpads.length === 0) &&
Router.getInstance().currentRoute === routes.PER_DEVICE_TOUCHPAD) {
getAnnouncerInstance().announce(
this.i18n('allTouchpadsDisconnectedA11yLabel'));

Router.getInstance().navigateTo(routes.DEVICE);
}
}
Expand All @@ -509,6 +515,8 @@ class SettingsDevicePageElement extends SettingsDevicePageElementBase {
if ((!this.pointingSticks || this.pointingSticks.length === 0) &&
Router.getInstance().currentRoute ===
routes.PER_DEVICE_POINTING_STICK) {
getAnnouncerInstance().announce(
this.i18n('allPointingSticksDisconnectedA11yLabel'));
Router.getInstance().navigateTo(routes.DEVICE);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export type PointingStickSettings =
InputDeviceSettingsTypes.PointingStickSettings;
export type DeviceSettings =
KeyboardSettings|TouchpadSettings|MouseSettings|PointingStickSettings;
export type InputDeviceType = Keyboard|Touchpad|Mouse|PointingStick;

export type InputDeviceSettingsPolicy =
InputDeviceSettingsTypes.InputDeviceSettingsPolicy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {DeviceSettings, InputDeviceSettingsPolicy, PolicyStatus} from './input_device_settings_types.js';
import {DeviceSettings, InputDeviceSettingsPolicy, InputDeviceType, PolicyStatus} from './input_device_settings_types.js';

function objectsAreEqual(
obj1: {[key: string]: any}, obj2: {[key: string]: any}): boolean {
Expand Down Expand Up @@ -61,3 +61,21 @@ export function getPrefPolicyFields(policy?: InputDeviceSettingsPolicy):
recommendedValue: undefined,
};
}

export function getDeviceStateChangesToAnnounce(
newDeviceList: InputDeviceType[],
prevDeviceList: InputDeviceType[]): {msgId: string, deviceNames: string[]} {
let msgId: string;
let devices: InputDeviceType[];
if (newDeviceList.length > prevDeviceList.length) {
devices =
newDeviceList.filter((device) => !prevDeviceList.includes(device));
msgId = 'deviceConnectedA11yLabel';
} else {
msgId = 'deviceDisconnectedA11yLabel';
devices =
prevDeviceList.filter((device) => !newDeviceList.includes(device));
}

return {msgId, deviceNames: devices.map(device => device.name)};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,25 @@ import '/shared/settings/controls/settings_slider.js';
import '/shared/settings/controls/settings_toggle_button.js';
import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';

import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {DeepLinkingMixin, DeepLinkingMixinInterface} from '../deep_linking_mixin.js';
import {DeepLinkingMixin} from '../deep_linking_mixin.js';
import {KeyboardPolicies} from '../mojom-webui/input_device_settings.mojom-webui.js';
import {Setting} from '../mojom-webui/setting.mojom-webui.js';
import {RouteObserverMixin, RouteObserverMixinInterface} from '../route_observer_mixin.js';
import {RouteObserverMixin} from '../route_observer_mixin.js';
import {Route, Router, routes} from '../router.js';

import {DevicePageBrowserProxy, DevicePageBrowserProxyImpl} from './device_page_browser_proxy.js';
import {Keyboard} from './input_device_settings_types.js';
import {getDeviceStateChangesToAnnounce} from './input_device_settings_utils.js';
import {getTemplate} from './per_device_keyboard.html.js';

const SettingsPerDeviceKeyboardElementBase =
DeepLinkingMixin(RouteObserverMixin(I18nMixin(PolymerElement))) as {
new (): PolymerElement & I18nMixinInterface &
RouteObserverMixinInterface & DeepLinkingMixinInterface,
};
DeepLinkingMixin(RouteObserverMixin(I18nMixin(PolymerElement)));

export class SettingsPerDeviceKeyboardElement extends
SettingsPerDeviceKeyboardElementBase {
Expand All @@ -59,6 +58,7 @@ export class SettingsPerDeviceKeyboardElement extends

keyboards: {
type: Array,
observer: 'onKeyboardListUpdated',
},

keyboardPolicies: {
Expand Down Expand Up @@ -130,6 +130,18 @@ export class SettingsPerDeviceKeyboardElement extends
this.attemptDeepLink();
}

private onKeyboardListUpdated(
newKeyboardList: Keyboard[], oldKeyboardList: Keyboard[]|undefined) {
if (!oldKeyboardList) {
return;
}
const {msgId, deviceNames} =
getDeviceStateChangesToAnnounce(newKeyboardList, oldKeyboardList);
for (const deviceName of deviceNames) {
getAnnouncerInstance().announce(this.i18n(msgId, deviceName));
}
}

private onShowKeyboardShortcutViewerClick(): void {
this.browserProxy.showKeyboardShortcutViewer();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ import '/shared/settings/controls/settings_slider.js';
import '/shared/settings/controls/settings_toggle_button.js';
import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';

import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {RouteObserverMixin} from '../route_observer_mixin.js';
import {Route, routes} from '../router.js';

import {Mouse, MousePolicies} from './input_device_settings_types.js';
import {getDeviceStateChangesToAnnounce} from './input_device_settings_utils.js';
import {getTemplate} from './per_device_mouse.html.js';

const SettingsPerDeviceMouseElementBase = RouteObserverMixin(PolymerElement);
const SettingsPerDeviceMouseElementBase =
RouteObserverMixin(I18nMixin(PolymerElement));

export class SettingsPerDeviceMouseElement extends
SettingsPerDeviceMouseElementBase {
Expand All @@ -43,6 +47,7 @@ export class SettingsPerDeviceMouseElement extends
return {
mice: {
type: Array,
observer: 'onMouseListUpdated',
},

mousePolicies: {
Expand All @@ -61,6 +66,18 @@ export class SettingsPerDeviceMouseElement extends
}
}

private onMouseListUpdated(
newMouseList: Mouse[], oldMouseList: Mouse[]|undefined) {
if (!oldMouseList) {
return;
}
const {msgId, deviceNames} =
getDeviceStateChangesToAnnounce(newMouseList, oldMouseList);
for (const deviceName of deviceNames) {
getAnnouncerInstance().announce(this.i18n(msgId, deviceName));
}
}

private computeIsLastDevice(index: number) {
return index === this.mice.length - 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ import '/shared/settings/controls/settings_slider.js';
import '/shared/settings/controls/settings_toggle_button.js';
import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';

import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {RouteObserverMixin} from '../route_observer_mixin.js';
import {Route, routes} from '../router.js';

import {PointingStick} from './input_device_settings_types.js';
import {getDeviceStateChangesToAnnounce} from './input_device_settings_utils.js';
import {getTemplate} from './per_device_pointing_stick.html.js';

const SettingsPerDevicePointingStickElementBase =
RouteObserverMixin(PolymerElement);
RouteObserverMixin(I18nMixin(PolymerElement));

export class SettingsPerDevicePointingStickElement extends
SettingsPerDevicePointingStickElementBase {
Expand All @@ -44,6 +47,7 @@ export class SettingsPerDevicePointingStickElement extends
return {
pointingSticks: {
type: Array,
observer: 'onPointingStickListUpdated',
},
};
}
Expand All @@ -57,6 +61,19 @@ export class SettingsPerDevicePointingStickElement extends
}
}

private onPointingStickListUpdated(
newPointingStickList: PointingStick[],
oldPointingStickList: PointingStick[]|undefined) {
if (!oldPointingStickList) {
return;
}
const {msgId, deviceNames} = getDeviceStateChangesToAnnounce(
newPointingStickList, oldPointingStickList);
for (const deviceName of deviceNames) {
getAnnouncerInstance().announce(this.i18n(msgId, deviceName));
}
}

private computeIsLastDevice(index: number) {
return index === this.pointingSticks.length - 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ import '/shared/settings/controls/settings_slider.js';
import '/shared/settings/controls/settings_toggle_button.js';
import 'chrome://resources/cr_elements/cr_slider/cr_slider.js';

import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {RouteObserverMixin} from '../route_observer_mixin.js';
import {Route, routes} from '../router.js';

import {Touchpad} from './input_device_settings_types.js';
import {getDeviceStateChangesToAnnounce} from './input_device_settings_utils.js';
import {getTemplate} from './per_device_touchpad.html.js';

const SettingsPerDeviceTouchpadElementBase = RouteObserverMixin(PolymerElement);
const SettingsPerDeviceTouchpadElementBase =
RouteObserverMixin(I18nMixin(PolymerElement));

export class SettingsPerDeviceTouchpadElement extends
SettingsPerDeviceTouchpadElementBase {
Expand All @@ -43,6 +47,7 @@ export class SettingsPerDeviceTouchpadElement extends
return {
touchpads: {
type: Array,
observer: 'onTouchpadListUpdated',
},
};
}
Expand All @@ -56,6 +61,18 @@ export class SettingsPerDeviceTouchpadElement extends
}
}

private onTouchpadListUpdated(
newTouchpadList: Touchpad[], oldTouchpadList: Touchpad[]|undefined) {
if (!oldTouchpadList) {
return;
}
const {msgId, deviceNames} =
getDeviceStateChangesToAnnounce(newTouchpadList, oldTouchpadList);
for (const deviceName of deviceNames) {
getAnnouncerInstance().announce(this.i18n(msgId, deviceName));
}
}

private computeIsLastDevice(index: number) {
return index === this.touchpads.length - 1;
}
Expand Down
10 changes: 10 additions & 0 deletions chrome/browser/ui/webui/settings/ash/device_section.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,16 @@ void DeviceSection::AddDevicePointersStrings(
base::FeatureList::IsEnabled(ash::features::kAllowScrollSettings);

webui::LocalizedString kPointersStrings[] = {
{"allMiceDisconnectedA11yLabel",
IDS_SETTINGS_PER_DEVICE_ALL_MICE_DISCONNECTED_A11Y_LABEL},
{"allTouchpadsDisconnectedA11yLabel",
IDS_SETTINGS_PER_DEVICE_ALL_TOUCHPADS_DISCONNECTED_A11Y_LABEL},
{"allPointingSticksDisconnectedA11yLabel",
IDS_SETTINGS_PER_DEVICE_ALL_POINTING_STICKS_DISCONNECTED_A11Y_LABEL},
{"deviceConnectedA11yLabel",
IDS_SETTINGS_PER_DEVICE_CONNECTED_A11Y_LABEL},
{"deviceDisconnectedA11yLabel",
IDS_SETTINGS_PER_DEVICE_DISCONNECTED_A11Y_LABEL},
{"mouseTitle", IDS_SETTINGS_MOUSE_TITLE},
{"builtInPointingStickName", IDS_SETTINGS_BUILT_IN_POINTING_STICK_NAME},
{"pointingStickTitle", IDS_SETTINGS_POINTING_STICK_TITLE},
Expand Down

0 comments on commit bb966d0

Please sign in to comment.