refactor: Improve accessibility of menus (#15302)

* refactor: improve menubar keyboard accessibility

* fix: create a temporary widget for tray icon context menu

* fix: focus menu bar with Alt when autohide is off

* fix: make menu bar focus work more like the native menus

* fix: only focus menu bar if it's not already focused

* fix: track accelerator registration to avoid duplicates

* docs: add docs for & notation in app menu item names

* fix: only try to activate accelerator if it's registered

* fix: add friend to monitor window focus change

* style: add <memory> include
This commit is contained in:
Heilig Benedek 2018-10-29 19:08:47 +01:00 committed by Charles Kerr
parent 00daff6ac8
commit 894ae1b3f5
13 changed files with 405 additions and 140 deletions

View file

@ -14,17 +14,24 @@
namespace atom {
MenuDelegate::MenuDelegate(MenuBar* menu_bar) : menu_bar_(menu_bar), id_(-1) {}
MenuDelegate::MenuDelegate(MenuBar* menu_bar)
: menu_bar_(menu_bar), id_(-1), hold_first_switch_(false) {}
MenuDelegate::~MenuDelegate() {}
void MenuDelegate::RunMenu(AtomMenuModel* model, views::MenuButton* button) {
void MenuDelegate::RunMenu(AtomMenuModel* model,
views::MenuButton* button,
ui::MenuSourceType source_type) {
gfx::Point screen_loc;
views::View::ConvertPointToScreen(button, &screen_loc);
// Subtract 1 from the height to make the popup flush with the button border.
gfx::Rect bounds(screen_loc.x(), screen_loc.y(), button->width(),
button->height() - 1);
if (source_type == ui::MENU_SOURCE_KEYBOARD) {
hold_first_switch_ = true;
}
id_ = button->tag();
adapter_.reset(new MenuModelAdapter(model));
@ -35,15 +42,18 @@ void MenuDelegate::RunMenu(AtomMenuModel* model, views::MenuButton* button) {
item,
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS));
menu_runner_->RunMenuAt(button->GetWidget()->GetTopLevelWidget(), button,
bounds, views::MENU_ANCHOR_TOPRIGHT,
ui::MENU_SOURCE_MOUSE);
bounds, views::MENU_ANCHOR_TOPRIGHT, source_type);
}
void MenuDelegate::ExecuteCommand(int id) {
for (Observer& obs : observers_)
obs.OnBeforeExecuteCommand();
adapter_->ExecuteCommand(id);
}
void MenuDelegate::ExecuteCommand(int id, int mouse_event_flags) {
for (Observer& obs : observers_)
obs.OnBeforeExecuteCommand();
adapter_->ExecuteCommand(id, mouse_event_flags);
}
@ -89,6 +99,9 @@ void MenuDelegate::WillHideMenu(views::MenuItemView* menu) {
}
void MenuDelegate::OnMenuClosed(views::MenuItemView* menu) {
for (Observer& obs : observers_)
obs.OnMenuClosed();
// Only switch to new menu when current menu is closed.
if (button_to_open_)
button_to_open_->Activate(nullptr);
@ -101,6 +114,11 @@ views::MenuItemView* MenuDelegate::GetSiblingMenu(
views::MenuAnchorPosition* anchor,
bool* has_mnemonics,
views::MenuButton**) {
if (hold_first_switch_) {
hold_first_switch_ = false;
return nullptr;
}
// TODO(zcbenz): We should follow Chromium's logics on implementing the
// sibling menu switches, this code is almost a hack.
views::MenuButton* button;