Closed Bug 901207 Opened 11 years ago Closed 11 years ago

Cmd/Ctrl+K should open menu panel when search bar was moved there

Categories

(Firefox :: Toolbars and Customization, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
Firefox 29

People

(Reporter: fb+mozdev, Assigned: jaws)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

(Whiteboard: [Australis:P5])

Attachments

(1 file, 4 obsolete files)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0 (Beta/Release)
Build ID: 20130729175331

Steps to reproduce:

Moved search bar into menu panel (like in Bug 901203).

Use the shortcut to focus the menu bar: Cmd+K (Mac)


Actual results:

Nothing.


Expected results:

Open menu panel, focus search bar.
(In reply to Florian Bender from comment #0)
> Actual results:
> 
> Nothing.

This is incorrect. Cmd+K actually moves me to https://www.google.de/?gws_rd=cr (last selected search provider). Sorry about that!
Hardware: x86 → x86_64
Whiteboard: [Australis:M?]
So does that fix the issue completely, or is there still a valid problem in this bug report?
Flags: needinfo?(fb+mozdev)
Comment 0 still applies. Comment 1 is just an update on "Actual results", i. e. it does not invalidate the bug report.
Flags: needinfo?(fb+mozdev)
Whiteboard: [Australis:M?] → [Australis:M?][Australis:P?]
This is how this keyboard shortcut has worked for a long time (if the search box is not visible, then it takes the user directly to the search engine webpage).

We *could* change this if the search box is in the menu panel, but I'm pretty confident we would be fine shipping with this bug unaddressed.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Whiteboard: [Australis:M?][Australis:P?] → [Australis:M?][Australis:P5]
Component: Untriaged → Toolbars and Customization
See Also: → 581276
OS: Mac OS X → All
Attached patch Patch (obsolete) — Splinter Review
I don't like how I had to duplicate some of the logic in the webSearch function. Maybe you have a better idea here?
Assignee: nobody → jaws
Status: NEW → ASSIGNED
Attachment #8345108 - Flags: review?(gijskruitbosch+bugs)
Attached patch Patch with test (obsolete) — Splinter Review
Attachment #8345108 - Attachment is obsolete: true
Attachment #8345108 - Flags: review?(gijskruitbosch+bugs)
Attachment #8345111 - Flags: review?(gijskruitbosch+bugs)
Comment on attachment 8345111 [details] [diff] [review]
Patch with test

Review of attachment 8345111 [details] [diff] [review]:
-----------------------------------------------------------------

Somewhat hesitant r+. If you want to do the overflow panel / refactor bits and/or adapt tests, I'd probably like to see the new patch, just for fun :-)

::: browser/base/content/browser.js
@@ +2931,5 @@
>  #endif
> +    let searchBar = this.searchBar;
> +    let placement = CustomizableUI.getPlacementOfWidget("search-container");
> +    if (placement && placement.area == CustomizableUI.AREA_PANEL) {
> +      PanelUI.show({type: "command"}).then(() => {

I think Blair updated PanelUI.show to work without passing an event. If my memory is correct, that would be nicer here.

@@ +2936,5 @@
> +        // The panel is not constructed until the first time it is shown.
> +        searchBar = this.searchBar;
> +        searchBar.select();
> +        if (document.activeElement != searchBar.textbox.inputField)
> +          openUILinkIn(Services.search.defaultEngine.searchForm, "current");

Yeah, hmm. Duplication is sad, but I don't really see a clever thing to do here, short of writing a utility function of the form:

let OpenSearchPageIfFieldIsNotActive = (aSearchBar) => { if (!aSearchBar || ...) openUILinkIn(...); }

and using that in both places.

@@ +2945,5 @@
> +          FullScreen.mouseoverToggle(true);
> +        searchBar.select();
> +      }
> +      if (!searchBar || document.activeElement != searchBar.textbox.inputField)
> +        openUILinkIn(Services.search.defaultEngine.searchForm, "current");

Note that this still won't work for the overflow panel. Could be a followup, but you could do it here, too.

Come to think of it, it actually probably makes sense to do something like the following:

if (placement) {
  if (placement.area == CustomizableUI.AREA_PANEL) {
    PanelUI.show().then(onSearchbarShown);
    return;
  }
  if (placement.area == CustomizableUI.AREA_NAVBAR && searchBar &&
      searchBar.parentNode.classList.contains("overflowedItem")) {
    ToggleOverflowPanelOrSomething().then(onSearchbarShown);
    return;
  }
}
if (searchBar && window.fullScreen) {
  FullScreen.mouseoverToggle(true);
}
onSearchbarShown();

Then in onSearchbarShown, if searchBar is not null, call select(), and if it's null or if the select failed to focus it, call openUILinkIn.

Does that make sense? It's still not the prettiest, but I don't know how to simplify it further.

::: browser/components/customizableui/content/panelUI.js
@@ +148,5 @@
>        let keyboardOpened = aEvent && aEvent.sourceEvent &&
>                             aEvent.sourceEvent.target.localName == "key";
>        this.panel.setAttribute("noautofocus", !keyboardOpened);
>        this.panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
> +  

Nit: trailing whitespace

@@ +157,3 @@
>      });
> +
> +    return deferred.promise;

This makes me happy. I think this means we can transition the head.js tests for this (and/or any tests that call PanelUI.open individually) to use this promise rather than rolling their own. Could you file a followup patch/bug to do that, please?

::: browser/components/customizableui/test/browser_901207_searchbar_in_panel.js
@@ +18,5 @@
> +      is(document.activeElement, searchbar.textbox.inputField, "The searchbar should be focused");
> +
> +      let hiddenPanelPromise = promisePanelHidden(window);
> +      EventUtils.synthesizeKey("VK_ESCAPE", {});
> +      yield hiddenPanelPromise;

Maybe also check what happens if the panel is already open? You added code for that case, probably good to check nobody breaks it.
Attachment #8345111 - Flags: review?(gijskruitbosch+bugs) → review+
Attached patch Patch v1.1 (obsolete) — Splinter Review
Updated patch with more test cases and handling the overflow panel. The test was failing with the overflow panel, and I believe that it has to do with which event listener runs first (I saw this using the Browser Debugger). The executeSoon fixes this, but it's crappy :(
Attachment #8345111 - Attachment is obsolete: true
Attachment #8345461 - Flags: review?(gijskruitbosch+bugs)
Attached patch Patch v1.2 (obsolete) — Splinter Review
Now with a less-ugly waitForCondition :)
Attachment #8345461 - Attachment is obsolete: true
Attachment #8345461 - Flags: review?(gijskruitbosch+bugs)
Attachment #8345473 - Flags: review?(gijskruitbosch+bugs)
Comment on attachment 8345473 [details] [diff] [review]
Patch v1.2

Review of attachment 8345473 [details] [diff] [review]:
-----------------------------------------------------------------

Hrm. This code is strange, though. What's up with checking for the "showing" state?

::: browser/components/customizableui/content/panelUI.js
@@ +124,5 @@
> +      deferred.resolve();
> +      return deferred.promise;
> +    }
> +    if (this.panel.state == "showing") {
> +      return deferred.promise;

This is strange. You're returning a promise but you're never resolving it. How does that work?

::: browser/components/customizableui/src/CustomizableUI.jsm
@@ +2846,5 @@
> +      deferred.resolve();
> +      return deferred.promise;
> +    }
> +    if (this._panel.state == "showing")
> +      return deferred.promise;

This is strange. You're returning a promise but you're never resolving it. How does that work?

@@ +2851,5 @@
> +    let doc = this._panel.ownerDocument;
> +    this._panel.hidden = false;
> +    let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
> +    this._panel.openPopup(anchor || this._chevron, "bottomcenter topright");
> +    this._chevron.open = !this._chevron.open;

Shouldn't this just be = true?

::: browser/components/customizableui/test/browser_901207_searchbar_in_panel.js
@@ +14,5 @@
> +      let shownPanelPromise = promisePanelShown(window);
> +      EventUtils.synthesizeKey("k", { ctrlKey: true });
> +      yield shownPanelPromise;
> +
> +      info(document.activeElement.id);

Nit: Please add text before this so it's clear what you're echo'ing.

@@ +38,5 @@
> +      PanelUI.toggle({type: "command"});
> +      yield shownPanelPromise;
> +
> +      EventUtils.synthesizeKey("k", { ctrlKey: true });
> +      info(document.activeElement.id);

Ditto

@@ +69,5 @@
> +      EventUtils.synthesizeKey("k", { ctrlKey: true });
> +      yield shownPanelPromise;
> +
> +      let chevron = document.getElementById("nav-bar-overflow-button");
> +      yield waitForCondition(function() chevron.open);

Nit: add an info() here too, please
Attachment #8345473 - Flags: review?(gijskruitbosch+bugs) → feedback+
Attached patch Patch v1.3Splinter Review
I was checking for popupshowing just in case there was some way that this code was getting called twice (once to start showing the popup and then again before the popup was shown, but then the promise will be a different instance). I've removed it now.
Attachment #8345473 - Attachment is obsolete: true
Attachment #8345536 - Flags: review?(gijskruitbosch+bugs)
Comment on attachment 8345536 [details] [diff] [review]
Patch v1.3

Review of attachment 8345536 [details] [diff] [review]:
-----------------------------------------------------------------

r=me, but see below for some nits

::: browser/components/customizableui/src/CustomizableUI.jsm
@@ +2849,5 @@
> +    let doc = this._panel.ownerDocument;
> +    this._panel.hidden = false;
> +    let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
> +    this._panel.openPopup(anchor || this._chevron, "bottomcenter topright");
> +    this._chevron.open = !this._chevron.open;

You missed this nit, I think? Just make this say = true (do we update it elsewhere, e.g. if you hide the panel with escape? I noticed the _onClickChevron method does it, but it'd be good to know we don't leave this in an inconsistent state)

::: browser/components/customizableui/test/browser_901207_searchbar_in_panel.js
@@ +14,5 @@
> +      let shownPanelPromise = promisePanelShown(window);
> +      EventUtils.synthesizeKey("k", { ctrlKey: true });
> +      yield shownPanelPromise;
> +
> +      info("Active element: " + descriptionForElement(document.activeElement));

Nit: just push down all of this line into the function, ie make it logActiveElement() and hardcode the "Active element: " and document.activeElement bits inside the function, as that's all we use it for in this file. Either that or pull it out into head.js. :-)
Attachment #8345536 - Flags: review?(gijskruitbosch+bugs) → review+
https://hg.mozilla.org/integration/fx-team/rev/3332e2f1ede3
Flags: in-testsuite+
Hardware: x86_64 → All
Whiteboard: [Australis:M?][Australis:P5] → [Australis:P5]
Depends on: 948980
https://hg.mozilla.org/mozilla-central/rev/3cafeb339fac
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 29
Depends on: 949365
No longer blocks: 949428
Depends on: 949428
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: