Commit 9baf1e60 authored by Michael Checo's avatar Michael Checo Committed by Commit Bot

Reland Printer settings: Make saved/nearby printers use FocusRowBehavior

This is a reland of 4f4586fd

Issue: FocusRowBehavior was not initializing properly which caused
  "keydown" events to target the Polymer element itself, most likely
  through event retargeting (http://shortn/_Nfy2DTMeen).

Fix: After populating nearby printers, wait for the next render of the
  nearby printers page to ensure the FocusRowBehavior setup is
  completed. With this change, the element with the "focus-row-control"
  attribute now consistently becomes the focused element when
  navigating through the printer entries.

Original change's description:
> Printer settings: Make saved/nearby printers use FocusRowBehavior
>
> Description:
>  This change allows users to tab to the first printer in the saved
>  and nearby printer lists and use the arrow keys to navigate the
>  remaining printers. Users can also use the arrow keys to navigate
>  through a printer entry's associated buttons/icons. Lastly, the
>  printer entry row will be highlighted (blue background) if it is
>  being focused.
>
> Screenshots:
>  - http://shortn/_Fqf1Nn9qjF nearby printers
>  - http://shortn/_BSspETkjzV saved printers
>
> Bug: 987422
> Test: gtest_filter=OSSettingsCupsPrinterLandingPageV3Test.All
> Change-Id: I68fc5fc3ff2ceec88ce81f95da5b451a6ad3beb1
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2399601
> Reviewed-by: Jimmy Gong <jimmyxgong@chromium.org>
> Commit-Queue: Michael Checo <michaelcheco@google.com>
> Cr-Commit-Position: refs/heads/master@{#809354}

Bug: 987422
Change-Id: I0982fe466e2c16d2b5b4a0f364808e223a668793
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2432306
Commit-Queue: Michael Checo <michaelcheco@google.com>
Reviewed-by: default avatarJimmy Gong <jimmyxgong@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815456}
parent 56243fdf
......@@ -131,6 +131,7 @@ js_library("cups_printers_entry") {
deps = [
":cups_printer_types",
":cups_printers_browser_proxy",
"//ui/webui/resources/js/cr/ui:focus_row_behavior",
]
}
......@@ -311,7 +312,10 @@ js_library("cups_printers_browser_proxy.m") {
js_library("cups_printers_entry.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.m.js" ]
deps = [ ":cups_printer_types.m" ]
deps = [
":cups_printer_types.m",
"//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
]
extra_deps = [ ":cups_printers_entry_module" ]
}
......
......@@ -28,7 +28,10 @@
<iron-list class="list-frame vertical-list flex-auto" id="printerEntryList"
items="[[filteredPrinters_]]">
<template>
<settings-cups-printers-entry printer-entry="[[item]]">
<settings-cups-printers-entry printer-entry="[[item]]"
tabindex$="[[tabIndex]]" last-focused="{{lastFocused_}}"
list-blurred="{{listBlurred_}}" focus-row-index="[[index]]"
iron-list-tab-index="[[tabIndex]]">
</settings-cups-printers-entry>
</template>
</iron-list>
......
......@@ -56,6 +56,18 @@ Polymer({
type: Array,
value: () => [],
},
/**
* Used by FocusRowBehavior to track the last focused element on a row.
* @private
*/
lastFocused_: Object,
/**
* Used by FocusRowBehavior to track if the list has been blurred.
* @private
*/
listBlurred_: Boolean,
},
listeners: {
......
......@@ -5,53 +5,74 @@
<link rel="import" href="cups_printers_browser_proxy.html">
<link rel="import" href="../../settings_shared_css.html">
<link rel="import" href="chrome://resources/html/load_time_data.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html">
<dom-module id="settings-cups-printers-entry">
<template>
<style include="settings-shared">
.icon-more-vert {
background-color: none;
}
.printer-name {
flex: 1;
}
.list-item:focus-within {
background-color: var(--google-blue-50);
outline: none;
}
</style>
<div id="entry" class="list-item" focus-row-container>
<div class="printer-name text-elide">
<span id="printerName" aria-hidden="true">
[[printerEntry.printerInfo.printerName]]
</span>
<div id="printerSubtext" hidden="[[!subtext]]" class="secondary"
aria-hidden="true">
[[subtext]]
<div focus-row-container>
<div id="entry" class="list-item" focus-row-control focus-type="entry">
<div class="printer-name text-elide">
<span id="printerName" aria-hidden="true">
[[printerEntry.printerInfo.printerName]]
</span>
<div id="printerSubtext" hidden="[[!subtext]]" class="secondary"
aria-hidden="true">
[[subtext]]
</div>
</div>
<template is="dom-if"
if="[[isSavedPrinter_(printerEntry.printerType)]]">
<cr-icon-button id="moreActions" class="icon-more-vert"
on-click="onOpenActionMenuTap_" title="$i18n{moreActions}"
aria-labelledby="printerName" focus-row-control
focus-type="moreActions" tabindex$="[[tabindex]]">
</cr-icon-button>
</template>
<template is="dom-if"
if="[[isDiscoveredPrinter_(printerEntry.printerType)]]">
<cr-button id="setupPrinterButton"
on-click="onAddDiscoveredPrinterTap_"
aria-label$="[[getSetupButtonAria_()]]"
focus-row-control
focus-type="setupPrinterButton">
$i18n{setupPrinter}
</cr-button>
</template>
<template is="dom-if"
if="[[isAutomaticPrinter_(printerEntry.printerType)]]">
<cr-button id="automaticPrinterButton" class="save-printer-button"
on-click="onAddAutomaticPrinterTap_"
aria-label$="[[getSaveButtonAria_()]]"
focus-row-control
focus-type="automaticPrinterButton">
$i18n{savePrinter}
</cr-button>
</template>
<template is="dom-if"
if="[[isPrintServerPrinter_(printerEntry.printerType)]]">
<cr-button id="savePrinterButton"
class="save-printer-button" on-click="onAddServerPrinterTap_"
aria-label$="[[getSaveButtonAria_()]]"
focus-row-control
focus-type="savePrinterButton">
$i18n{savePrinter}
</cr-button>
</template>
</div>
<template is="dom-if" if="[[isSavedPrinter_(printerEntry.printerType)]]">
<cr-icon-button id="moreActions" class="icon-more-vert"
on-click="onOpenActionMenuTap_" title="$i18n{moreActions}"
aria-labelledby="printerName">
</cr-icon-button>
</template>
<template is="dom-if"
if="[[isDiscoveredPrinter_(printerEntry.printerType)]]">
<cr-button id="setupPrinterButton"
on-click="onAddDiscoveredPrinterTap_"
aria-label$="[[getSetupButtonAria_()]]">
$i18n{setupPrinter}
</cr-button>
</template>
<template is="dom-if"
if="[[isAutomaticPrinter_(printerEntry.printerType)]]">
<cr-button class="save-printer-button"
on-click="onAddAutomaticPrinterTap_"
aria-label$="[[getSaveButtonAria_()]]">
$i18n{savePrinter}
</cr-button>
</template>
<template is="dom-if"
if="[[isPrintServerPrinter_(printerEntry.printerType)]]">
<cr-button class="save-printer-button" on-click="onAddServerPrinterTap_"
aria-label$="[[getSaveButtonAria_()]]">
$i18n{savePrinter}
</cr-button>
</template>
</div>
</template>
<script src="cups_printers_entry.js"></script>
......
......@@ -9,6 +9,9 @@
Polymer({
is: 'settings-cups-printers-entry',
behaviors: [
cr.ui.FocusRowBehavior,
],
properties: {
/** @type {!PrinterListEntry} */
printerEntry: Object,
......
......@@ -63,7 +63,10 @@
<iron-list class="list-frame vertical-list flex-auto" id="printerEntryList"
items="[[filteredPrinters_]]">
<template>
<settings-cups-printers-entry printer-entry="[[item]]">
<settings-cups-printers-entry printer-entry="[[item]]"
tabindex$="[[tabIndex]]" last-focused="{{lastFocused_}}"
list-blurred="{{listBlurred_}}" focus-row-index="[[index]]"
iron-list-tab-index="[[tabIndex]]">
</settings-cups-printers-entry>
</template>
</iron-list>
......
......@@ -96,6 +96,18 @@ Polymer({
type: Boolean,
value: false,
},
/**
* Used by FocusRowBehavior to track the last focused element on a row.
* @private
*/
lastFocused_: Object,
/**
* Used by FocusRowBehavior to track if the list has been blurred.
* @private
*/
listBlurred_: Boolean,
},
listeners: {
......
......@@ -18,6 +18,18 @@
// #import {waitAfterNextRender} from 'chrome://test/test_util.m.js';
// clang-format on
const arrowUpEvent = new KeyboardEvent(
'keydown', {cancelable: true, key: 'ArrowUp', keyCode: 38});
const arrowDownEvent = new KeyboardEvent(
'keydown', {cancelable: true, key: 'ArrowDown', keyCode: 40});
const arrowLeftEvent = new KeyboardEvent(
'keydown', {cancelable: true, key: 'ArrowLeft', keyCode: 37});
const arrowRightEvent = new KeyboardEvent(
'keydown', {cancelable: true, key: 'ArrowRight', keyCode: 39});
/**
* @param {!HTMLElement} printerEntry
* @private
......@@ -615,6 +627,37 @@ suite('CupsSavedPrintersTests', function() {
});
});
test('NavigateSavedPrintersList', function() {
createCupsPrinterPage([
cups_printer_test_util.createCupsPrinterInfo('google', '4', 'id4'),
cups_printer_test_util.createCupsPrinterInfo('test1', '1', 'id1'),
cups_printer_test_util.createCupsPrinterInfo('test2', '2', 'id2'),
]);
return cupsPrintersBrowserProxy.whenCalled('getCupsPrintersList')
.then(async () => {
// Wait for saved printers to populate.
Polymer.dom.flush();
savedPrintersElement = page.$$('settings-cups-saved-printers');
assertTrue(!!savedPrintersElement);
const printerEntryList = savedPrintersElement.$$('#printerEntryList');
const printerListEntries =
cups_printer_test_util.getPrinterEntries(savedPrintersElement);
printerEntryList.focus();
printerEntryList.dispatchEvent(arrowDownEvent);
Polymer.dom.flush();
assertEquals(printerListEntries[1], getDeepActiveElement());
printerEntryList.dispatchEvent(arrowDownEvent);
Polymer.dom.flush();
assertEquals(printerListEntries[2], getDeepActiveElement());
printerEntryList.dispatchEvent(arrowUpEvent);
Polymer.dom.flush();
assertEquals(printerListEntries[1], getDeepActiveElement());
printerEntryList.dispatchEvent(arrowUpEvent);
Polymer.dom.flush();
assertEquals(printerListEntries[0], getDeepActiveElement());
});
});
test('Deep link to saved printers', async () => {
loadTimeData.overrideValues({
isDeepLinkingEnabled: true,
......@@ -1201,6 +1244,59 @@ suite('CupsNearbyPrintersTests', function() {
});
});
test('NavigateNearbyPrinterList', function() {
const discoveredPrinterList = [
cups_printer_test_util.createCupsPrinterInfo('first', '3', 'id3'),
cups_printer_test_util.createCupsPrinterInfo('second', '4', 'id4'),
cups_printer_test_util.createCupsPrinterInfo('third', '2', 'id5'),
];
return test_util.flushTasks().then(async () => {
nearbyPrintersElement = page.$$('settings-cups-nearby-printers');
// Block so that FocusRowBehavior.attached can run.
await test_util.waitAfterNextRender(nearbyPrintersElement);
assertTrue(!!nearbyPrintersElement);
// Simuluate finding nearby printers.
cr.webUIListenerCallback(
'on-nearby-printers-changed', [], discoveredPrinterList);
Polymer.dom.flush();
// Wait one more time to ensure that async setup in FocusRowBehavior has
// executed.
await test_util.waitAfterNextRender(nearbyPrintersElement);
const nearbyPrinterEntries =
cups_printer_test_util.getPrinterEntries(nearbyPrintersElement);
const printerEntryList = nearbyPrintersElement.$$('#printerEntryList');
nearbyPrinterEntries[0].$$('#entry').focus();
assertEquals(
nearbyPrinterEntries[0].$$('#entry'), getDeepActiveElement());
// Ensure that we can navigate through items in a row
getDeepActiveElement().dispatchEvent(arrowRightEvent);
assertEquals(
nearbyPrinterEntries[0].$$('#setupPrinterButton'),
getDeepActiveElement());
getDeepActiveElement().dispatchEvent(arrowLeftEvent);
assertEquals(
nearbyPrinterEntries[0].$$('#entry'), getDeepActiveElement());
// Ensure that we can navigate through printer rows
printerEntryList.dispatchEvent(arrowDownEvent);
assertEquals(
nearbyPrinterEntries[1].$$('#entry'), getDeepActiveElement());
printerEntryList.dispatchEvent(arrowDownEvent);
assertEquals(
nearbyPrinterEntries[2].$$('#entry'), getDeepActiveElement());
printerEntryList.dispatchEvent(arrowUpEvent);
assertEquals(
nearbyPrinterEntries[1].$$('#entry'), getDeepActiveElement());
printerEntryList.dispatchEvent(arrowUpEvent);
assertEquals(
nearbyPrinterEntries[0].$$('#entry'), getDeepActiveElement());
});
});
test('addingDiscoveredPrinterIsSuccessful', function() {
const automaticPrinterList = [];
const discoveredPrinterList =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment