Commit 7480fd4e authored by Luciano Pacheco's avatar Luciano Pacheco Committed by Commit Bot

Files app: Fix multi-menu to follow its button

Use ResizeObserver to observe the container parent of toolbar buttons,
when it resizes, means that the buttons have moved, in this case
re-position the dropdown menu to align with its button.

This fixes the issue when the user clicks from the search box in a
button with dropdown and the search collapses and moves the dropdown
button.

Bug: 1063337
Change-Id: Ia8ae426778a25ebf472631b1903b884454d8f33f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2114316
Commit-Queue: Noel Gordon <noel@chromium.org>
Reviewed-by: default avatarNoel Gordon <noel@chromium.org>
Auto-Submit: Luciano Pacheco <lucmult@chromium.org>
Cr-Commit-Position: refs/heads/master@{#752777}
parent 927e52fe
...@@ -458,7 +458,8 @@ WRAPPED_INSTANTIATE_TEST_SUITE_P( ...@@ -458,7 +458,8 @@ WRAPPED_INSTANTIATE_TEST_SUITE_P(
TestCase("toolbarDeleteEntry"), TestCase("toolbarDeleteEntry"),
TestCase("toolbarRefreshButtonWithSelection").EnableArc(), TestCase("toolbarRefreshButtonWithSelection").EnableArc(),
TestCase("toolbarAltACommand").FilesNg(), TestCase("toolbarAltACommand").FilesNg(),
TestCase("toolbarRefreshButtonHiddenInRecents"))); TestCase("toolbarRefreshButtonHiddenInRecents"),
TestCase("toolbarMultiMenuFollowsButton")));
WRAPPED_INSTANTIATE_TEST_SUITE_P( WRAPPED_INSTANTIATE_TEST_SUITE_P(
QuickView, /* quick_view.js */ QuickView, /* quick_view.js */
......
...@@ -430,6 +430,7 @@ js_library("multi_menu") { ...@@ -430,6 +430,7 @@ js_library("multi_menu") {
"//ui/webui/resources/js/cr/ui:menu_item", "//ui/webui/resources/js/cr/ui:menu_item",
"//ui/webui/resources/js/cr/ui:position_util", "//ui/webui/resources/js/cr/ui:position_util",
] ]
externs_list = [ "$externs_path/pending.js" ]
} }
js_unittest("multi_menu_unittest") { js_unittest("multi_menu_unittest") {
......
...@@ -60,6 +60,12 @@ cr.define('cr.ui', () => { ...@@ -60,6 +60,12 @@ cr.define('cr.ui', () => {
/** @private {?cr.ui.Menu} */ /** @private {?cr.ui.Menu} */
this.menu_ = null; this.menu_ = null;
/** @private {?ResizeObserver} */
this.observer_ = null;
/** @private {?Element} */
this.observedElement_ = null;
throw new Error('Designed to decorate elements'); throw new Error('Designed to decorate elements');
} }
...@@ -121,6 +127,12 @@ cr.define('cr.ui', () => { ...@@ -121,6 +127,12 @@ cr.define('cr.ui', () => {
this.menu = menu; this.menu = menu;
} }
// Align the menu if the button moves. When the button moves, the parent
// container resizes.
this.observer_ = new ResizeObserver(() => {
this.positionMenu_();
});
// An event tracker for events we only connect to while the menu is // An event tracker for events we only connect to while the menu is
// displayed. // displayed.
this.showingEvents_ = new EventTracker(); this.showingEvents_ = new EventTracker();
...@@ -517,6 +529,8 @@ cr.define('cr.ui', () => { ...@@ -517,6 +529,8 @@ cr.define('cr.ui', () => {
this.showingEvents_.add(win, 'resize', this); this.showingEvents_.add(win, 'resize', this);
this.showingEvents_.add(this.menu, 'contextmenu', this); this.showingEvents_.add(this.menu, 'contextmenu', this);
this.showingEvents_.add(this.menu, 'activate', this); this.showingEvents_.add(this.menu, 'activate', this);
this.observedElement_ = this.parentElement;
this.observer_.observe(this.observedElement_);
this.positionMenu_(); this.positionMenu_();
if (shouldSetFocus) { if (shouldSetFocus) {
...@@ -596,6 +610,8 @@ cr.define('cr.ui', () => { ...@@ -596,6 +610,8 @@ cr.define('cr.ui', () => {
this.focus(); this.focus();
} }
this.observer_.unobserve(this.observedElement_);
const event = new UIEvent( const event = new UIEvent(
'menuhide', {bubbles: true, cancelable: false, view: window}); 'menuhide', {bubbles: true, cancelable: false, view: window});
this.dispatchEvent(event); this.dispatchEvent(event);
......
...@@ -172,7 +172,7 @@ ...@@ -172,7 +172,7 @@
// Open Files app on Downloads. // Open Files app on Downloads.
const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [entry], []); const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [entry], []);
// Measure the width of the search box when it's collapsed. // Search box should start collapsed.
await remoteCall.waitForElement(appId, '#search-wrapper[collapsed]'); await remoteCall.waitForElement(appId, '#search-wrapper[collapsed]');
// Click the toolbar search button. // Click the toolbar search button.
......
...@@ -143,3 +143,50 @@ testcase.toolbarAltACommand = async () => { ...@@ -143,3 +143,50 @@ testcase.toolbarAltACommand = async () => {
const cssClasses = focusedElement.attributes['class'] || ''; const cssClasses = focusedElement.attributes['class'] || '';
chrome.test.assertTrue(cssClasses.includes('menu-button')); chrome.test.assertTrue(cssClasses.includes('menu-button'));
}; };
/**
* Tests that the menu drop down follows the button if the button moves. This
* happens when the search box is expanded and then collapsed.
*/
testcase.toolbarMultiMenuFollowsButton = async () => {
const entry = ENTRIES.hello;
// Open Files app on Downloads.
const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [entry], []);
// Override the tasks so the "Open" button becomes a dropdown button.
await remoteCall.callRemoteTestUtil(
'overrideTasks', appId, [DOWNLOADS_FAKE_TASKS]);
// Select an entry in the file list.
chrome.test.assertTrue(await remoteCall.callRemoteTestUtil(
'selectFile', appId, [entry.nameText]));
// Click the toolbar search button.
await remoteCall.waitAndClickElement(appId, '#search-button');
// Wait for the search box to expand.
await remoteCall.waitForElementLost(appId, '#search-wrapper[collapsed]');
// Click the toolbar "Open" dropdown button.
await remoteCall.simulateUiClick(appId, '#tasks');
// Wait for the search box to collapse.
await remoteCall.waitForElement(appId, '#search-wrapper[collapsed]');
// Check that the dropdown menu and "Open" button are aligned.
const caller = getCaller();
await repeatUntil(async () => {
const openButton =
await remoteCall.waitForElementStyles(appId, '#tasks', ['width']);
const menu =
await remoteCall.waitForElementStyles(appId, '#tasks-menu', ['width']);
if (openButton.renderedLeft !== menu.renderedLeft) {
return pending(
caller,
`Waiting for the menu and button to be aligned: ` +
`${openButton.renderedLeft} != ${menu.renderedLeft}`);
}
});
};
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