From bc1cee6f1db69579e72287bdd1aca442ca904ec2 Mon Sep 17 00:00:00 2001 From: msw Date: Mon, 21 Mar 2016 11:08:26 -0700 Subject: Add simple mash context menu support. Add ash/mus/context_menu_mus.* for mash context menus. (populates local ash items like ash_shell_with_content) Tangential ShelfView refactoring (can be split). BUG=557406 TEST="chrome --mash" context menus appear. R=sky@chromium.org Review URL: https://codereview.chromium.org/1760743002 Cr-Commit-Position: refs/heads/master@{#382326} --- ash/mus/BUILD.gn | 2 + ash/mus/DEPS | 2 +- ash/mus/context_menu_mus.cc | 59 +++++++++++++++++++++++ ash/mus/context_menu_mus.h | 46 ++++++++++++++++++ ash/mus/shell_delegate_mus.cc | 5 +- ash/shelf/shelf_view.cc | 108 ++++++++++++++---------------------------- ash/shelf/shelf_view.h | 11 ++--- 7 files changed, 151 insertions(+), 82 deletions(-) create mode 100644 ash/mus/context_menu_mus.cc create mode 100644 ash/mus/context_menu_mus.h (limited to 'ash') diff --git a/ash/mus/BUILD.gn b/ash/mus/BUILD.gn index 4ca9bac..d86ab22 100644 --- a/ash/mus/BUILD.gn +++ b/ash/mus/BUILD.gn @@ -10,6 +10,8 @@ import("//tools/grit/repack.gni") source_set("lib") { sources = [ + "context_menu_mus.cc", + "context_menu_mus.h", "keyboard_ui_mus.cc", "keyboard_ui_mus.h", "shelf_delegate_mus.cc", diff --git a/ash/mus/DEPS b/ash/mus/DEPS index 3ea1294..e0d3ce9 100644 --- a/ash/mus/DEPS +++ b/ash/mus/DEPS @@ -3,7 +3,7 @@ include_rules = [ "+cc", "+components/mus/common", "+components/mus/public", - "+mash/wm", + "+mash/wm/public/interfaces", "+mojo/common", "+mojo/converters", "+mojo/public", diff --git a/ash/mus/context_menu_mus.cc b/ash/mus/context_menu_mus.cc new file mode 100644 index 0000000..50f03a7 --- /dev/null +++ b/ash/mus/context_menu_mus.cc @@ -0,0 +1,59 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/mus/context_menu_mus.h" + +#include "ash/desktop_background/user_wallpaper_delegate.h" +#include "ash/shelf/shelf.h" +#include "ash/shelf/shelf_types.h" +#include "ash/shell.h" +#include "grit/ash_strings.h" + +namespace ash { + +ContextMenuMus::ContextMenuMus(ash::Shelf* shelf) + : ui::SimpleMenuModel(nullptr), shelf_(shelf), alignment_menu_(shelf) { + DCHECK(shelf_); + set_delegate(this); + AddCheckItemWithStringId(MENU_AUTO_HIDE, + IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE); + AddSubMenuWithStringId(MENU_ALIGNMENT_MENU, + IDS_ASH_SHELF_CONTEXT_MENU_POSITION, &alignment_menu_); +#if defined(OS_CHROMEOS) + AddItemWithStringId(MENU_CHANGE_WALLPAPER, IDS_AURA_SET_DESKTOP_WALLPAPER); +#endif +} + +ContextMenuMus::~ContextMenuMus() {} + +bool ContextMenuMus::IsCommandIdChecked(int command_id) const { + if (command_id == MENU_AUTO_HIDE) + return shelf_->GetAutoHideBehavior() == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; + return false; +} + +bool ContextMenuMus::IsCommandIdEnabled(int command_id) const { + Shell* shell = Shell::GetInstance(); + if (command_id == MENU_CHANGE_WALLPAPER) + return shell->user_wallpaper_delegate()->CanOpenSetWallpaperPage(); + return true; +} + +bool ContextMenuMus::GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) { + return false; +} + +void ContextMenuMus::ExecuteCommand(int command_id, int event_flags) { + if (command_id == MENU_AUTO_HIDE) { + shelf_->SetAutoHideBehavior(shelf_->GetAutoHideBehavior() == + SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS + ? SHELF_AUTO_HIDE_BEHAVIOR_NEVER + : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + } else if (command_id == MENU_CHANGE_WALLPAPER) { + Shell::GetInstance()->user_wallpaper_delegate()->OpenSetWallpaperPage(); + } +} + +} // namespace ash diff --git a/ash/mus/context_menu_mus.h b/ash/mus/context_menu_mus.h new file mode 100644 index 0000000..dfe327a --- /dev/null +++ b/ash/mus/context_menu_mus.h @@ -0,0 +1,46 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_MUS_CONTEXT_MENU_MUS_H_ +#define ASH_MUS_CONTEXT_MENU_MUS_H_ + +#include "ash/shelf/shelf_alignment_menu.h" +#include "base/macros.h" +#include "ui/base/models/simple_menu_model.h" + +namespace ash { + +class Shelf; + +// Context menu for mash. +// TODO(msw): Mimic logic in LauncherContextMenu. +class ContextMenuMus : public ui::SimpleMenuModel, + public ui::SimpleMenuModel::Delegate { + public: + explicit ContextMenuMus(Shelf* shelf); + ~ContextMenuMus() override; + + // ui::SimpleMenuModel::Delegate overrides: + bool IsCommandIdChecked(int command_id) const override; + bool IsCommandIdEnabled(int command_id) const override; + bool GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) override; + void ExecuteCommand(int command_id, int event_flags) override; + + private: + enum MenuItem { + MENU_AUTO_HIDE, + MENU_ALIGNMENT_MENU, + MENU_CHANGE_WALLPAPER, + }; + + Shelf* shelf_; + ShelfAlignmentMenu alignment_menu_; + + DISALLOW_COPY_AND_ASSIGN(ContextMenuMus); +}; + +} // namespace ash + +#endif // ASH_MUS_CONTEXT_MENU_MUS_H_ diff --git a/ash/mus/shell_delegate_mus.cc b/ash/mus/shell_delegate_mus.cc index 7f627e1..3ce7579 100644 --- a/ash/mus/shell_delegate_mus.cc +++ b/ash/mus/shell_delegate_mus.cc @@ -8,6 +8,7 @@ #include "ash/default_user_wallpaper_delegate.h" #include "ash/gpu_support_stub.h" #include "ash/media_delegate.h" +#include "ash/mus/context_menu_mus.h" #include "ash/mus/shelf_delegate_mus.h" #include "ash/session/session_state_delegate.h" #include "ash/system/tray/default_system_tray_delegate.h" @@ -95,6 +96,7 @@ class MediaDelegateStub : public MediaDelegate { } // namespace ShellDelegateMus::ShellDelegateMus() {} + ShellDelegateMus::~ShellDelegateMus() {} bool ShellDelegateMus::IsFirstRunAfterBoot() const { @@ -199,8 +201,7 @@ MediaDelegate* ShellDelegateMus::CreateMediaDelegate() { ui::MenuModel* ShellDelegateMus::CreateContextMenu(ash::Shelf* shelf, const ShelfItem* item) { - NOTIMPLEMENTED(); - return nullptr; + return new ContextMenuMus(shelf); } GPUSupport* ShellDelegateMus::CreateGPUSupport() { diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index d15cccd..e61e7aa 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc @@ -503,8 +503,7 @@ void ShelfView::UpdatePanelIconPosition(ShelfID id, } bool ShelfView::IsShowingMenu() const { - return (launcher_menu_runner_.get() && - launcher_menu_runner_->IsRunning()); + return launcher_menu_runner_.get() && launcher_menu_runner_->IsRunning(); } bool ShelfView::IsShowingOverflowBubble() const { @@ -1763,7 +1762,7 @@ void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event) { } } -bool ShelfView::ShowListMenuForView(const ShelfItem& item, +void ShelfView::ShowListMenuForView(const ShelfItem& item, views::View* source, const ui::Event& event) { ShelfItemDelegate* item_delegate = @@ -1774,39 +1773,29 @@ bool ShelfView::ShowListMenuForView(const ShelfItem& item, // Make sure we have a menu and it has at least two items in addition to the // application title and the 3 spacing separators. if (!list_menu_model.get() || list_menu_model->GetItemCount() <= 5) - return false; + return; - ShowMenu(list_menu_model.get(), - source, - gfx::Point(), - false, + context_menu_id_ = item.id; + ShowMenu(list_menu_model.get(), source, gfx::Point(), false, ui::GetMenuSourceTypeForEvent(event)); - return true; } void ShelfView::ShowContextMenuForView(views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) { - int view_index = view_model_->GetIndexOfView(source); - if (view_index == -1) { + const ShelfItem* item = ShelfItemForView(source); + if (!item) { Shell::GetInstance()->ShowContextMenu(point, source_type); return; } - context_menu_model_.reset(Shell::GetInstance()->delegate()->CreateContextMenu( - shelf_, &model_->items()[view_index])); - if (!context_menu_model_) + scoped_ptr context_menu_model( + Shell::GetInstance()->delegate()->CreateContextMenu(shelf_, item)); + if (!context_menu_model) return; - base::AutoReset reseter( - &context_menu_id_, - view_index == -1 ? 0 : model_->items()[view_index].id); - - ShowMenu(context_menu_model_.get(), - source, - point, - true, - source_type); + context_menu_id_ = item ? item->id : 0; + ShowMenu(context_menu_model.get(), source, point, true, source_type); } void ShelfView::ShowMenu(ui::MenuModel* menu_model, @@ -1818,77 +1807,54 @@ void ShelfView::ShowMenu(ui::MenuModel* menu_model, launcher_menu_runner_.reset(new views::MenuRunner( menu_model, context_menu ? views::MenuRunner::CONTEXT_MENU : 0)); - ScopedTargetRootWindow scoped_target( - source->GetWidget()->GetNativeView()->GetRootWindow()); + aura::Window* window = source->GetWidget()->GetNativeWindow(); + ScopedTargetRootWindow scoped_target(window->GetRootWindow()); - // Determine the menu alignment dependent on the shelf. views::MenuAnchorPosition menu_alignment = views::MENU_ANCHOR_TOPLEFT; - gfx::Rect anchor_point = gfx::Rect(click_point, gfx::Size()); + gfx::Rect anchor = gfx::Rect(click_point, gfx::Size()); if (!context_menu) { // Application lists use a bubble. - ShelfAlignment align = shelf_->alignment(); - anchor_point = source->GetBoundsInScreen(); - // It is possible to invoke the menu while it is sliding into view. To cover // that case, the screen coordinates are offsetted by the animation delta. - gfx::Vector2d offset = - source->GetWidget()->GetNativeWindow()->bounds().origin() - - source->GetWidget()->GetNativeWindow()->GetTargetBounds().origin(); - anchor_point.set_x(anchor_point.x() - offset.x()); - anchor_point.set_y(anchor_point.y() - offset.y()); - - // Shelf items can have an asymmetrical border for spacing reasons. - // Adjust anchor location for this. + anchor = source->GetBoundsInScreen() + + (window->GetTargetBounds().origin() - window->bounds().origin()); + + // Adjust the anchor location for shelf items with asymmetrical borders. if (source->border()) - anchor_point.Inset(source->border()->GetInsets()); + anchor.Inset(source->border()->GetInsets()); - switch (align) { - case SHELF_ALIGNMENT_BOTTOM: - menu_alignment = views::MENU_ANCHOR_BUBBLE_ABOVE; - break; - case SHELF_ALIGNMENT_LEFT: - menu_alignment = views::MENU_ANCHOR_BUBBLE_RIGHT; - break; - case SHELF_ALIGNMENT_RIGHT: - menu_alignment = views::MENU_ANCHOR_BUBBLE_LEFT; - break; - case SHELF_ALIGNMENT_TOP: - menu_alignment = views::MENU_ANCHOR_BUBBLE_BELOW; - break; - } + // Determine the menu alignment dependent on the shelf. + menu_alignment = shelf_->SelectValueForShelfAlignment( + views::MENU_ANCHOR_BUBBLE_ABOVE, views::MENU_ANCHOR_BUBBLE_RIGHT, + views::MENU_ANCHOR_BUBBLE_LEFT, views::MENU_ANCHOR_BUBBLE_BELOW); } - // If this gets deleted while we are in the menu, the shelf will be gone - // as well. + // If this is deleted while the menu is running, the shelf will also be gone. bool got_deleted = false; got_deleted_ = &got_deleted; ShelfWidget* shelf_widget = shelf_->shelf_widget(); shelf_widget->ForceUndimming(true); - // NOTE: if you convert to HAS_MNEMONICS be sure and update menu building - // code. - if (launcher_menu_runner_->RunMenuAt(source->GetWidget(), - NULL, - anchor_point, - menu_alignment, - source_type) == + // NOTE: if you convert to HAS_MNEMONICS be sure to update menu building code. + if (launcher_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, anchor, + menu_alignment, source_type) == views::MenuRunner::MENU_DELETED) { if (!got_deleted) { - got_deleted_ = NULL; + got_deleted_ = nullptr; + context_menu_id_ = 0; shelf_widget->ForceUndimming(false); } return; } - got_deleted_ = NULL; + got_deleted_ = nullptr; + context_menu_id_ = 0; shelf_widget->ForceUndimming(false); - // If it is a context menu and we are showing overflow bubble - // we want to hide overflow bubble. + // Hide the hide overflow bubble after showing a context menu for its items. if (owner_overflow_bubble_) owner_overflow_bubble_->HideBubbleAndRefreshButton(); - // Unpinning an item will reset the |launcher_menu_runner_| before coming - // here. + // Unpinning an item will reset |launcher_menu_runner_| before coming here. if (launcher_menu_runner_) closing_event_time_ = launcher_menu_runner_->closing_event_time(); Shell::GetInstance()->UpdateShelfVisibility(); @@ -1934,10 +1900,8 @@ bool ShelfView::IsRepostEvent(const ui::Event& event) { } const ShelfItem* ShelfView::ShelfItemForView(const views::View* view) const { - int view_index = view_model_->GetIndexOfView(view); - if (view_index == -1) - return NULL; - return &(model_->items()[view_index]); + const int view_index = view_model_->GetIndexOfView(view); + return (view_index < 0) ? nullptr : &(model_->items()[view_index]); } bool ShelfView::ShouldShowTooltipForView(const views::View* view) const { diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index ccfb1f4..1343283 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h @@ -274,12 +274,11 @@ class ASH_EXPORT ShelfView : public views::View, // Overridden from views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; - // Show the list of all running items for this |item|. It will return true - // when the menu was shown and false if there were no possible items to - // choose from. |source| specifies the view which is responsible for showing - // the menu, and the bubble will point towards it. + // Show a list of all running items for this shelf |item|; it only shows a + // menu if there are multiple running items. |source| specifies the view + // responsible for showing the menu, and the bubble will point towards it. // The |event_flags| are the flags of the event which triggered this menu. - bool ShowListMenuForView(const ShelfItem& item, + void ShowListMenuForView(const ShelfItem& item, views::View* source, const ui::Event& event); @@ -366,8 +365,6 @@ class ASH_EXPORT ShelfView : public views::View, scoped_ptr focus_search_; - scoped_ptr context_menu_model_; - scoped_ptr launcher_menu_runner_; base::ObserverList observers_; -- cgit v1.1