123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- // Copyright 2018 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/app_menu/app_menu_model_adapter.h"
- #include "ash/app_menu/notification_menu_controller.h"
- #include "ash/constants/ash_features.h"
- #include "ash/public/cpp/shelf_model.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/metrics/histogram_macros.h"
- #include "ui/accessibility/ax_enums.mojom.h"
- #include "ui/base/models/simple_menu_model.h"
- #include "ui/views/controls/menu/menu_item_view.h"
- #include "ui/views/controls/menu/menu_model_adapter.h"
- #include "ui/views/controls/menu/menu_runner.h"
- #include "ui/views/controls/menu/submenu_view.h"
- #include "ui/views/widget/widget.h"
- namespace ash {
- namespace {
- // The UMA histogram that logs the commands which are executed on non-app
- // context menus.
- constexpr char kNonAppContextMenuExecuteCommand[] =
- "Apps.ContextMenuExecuteCommand.NotFromApp";
- constexpr char kNonAppContextMenuExecuteCommandInTablet[] =
- "Apps.ContextMenuExecuteCommand.NotFromApp.TabletMode";
- constexpr char kNonAppContextMenuExecuteCommandInClamshell[] =
- "Apps.ContextMenuExecuteCommand.NotFromApp.ClamshellMode";
- // The UMA histogram that logs the commands which are executed on app context
- // menus.
- constexpr char kAppContextMenuExecuteCommand[] =
- "Apps.ContextMenuExecuteCommand.FromApp";
- constexpr char kAppContextMenuExecuteCommandInTablet[] =
- "Apps.ContextMenuExecuteCommand.FromApp.TabletMode";
- constexpr char kAppContextMenuExecuteCommandInClamshell[] =
- "Apps.ContextMenuExecuteCommand.FromApp.ClamshellMode";
- } // namespace
- AppMenuModelAdapter::AppMenuModelAdapter(
- const std::string& app_id,
- std::unique_ptr<ui::SimpleMenuModel> model,
- views::Widget* widget_owner,
- ui::MenuSourceType source_type,
- base::OnceClosure on_menu_closed_callback,
- bool is_tablet_mode)
- : views::MenuModelAdapter(model.get()),
- app_id_(app_id),
- model_(std::move(model)),
- widget_owner_(widget_owner),
- source_type_(source_type),
- on_menu_closed_callback_(std::move(on_menu_closed_callback)),
- is_tablet_mode_(is_tablet_mode) {}
- AppMenuModelAdapter::~AppMenuModelAdapter() = default;
- void AppMenuModelAdapter::Run(const gfx::Rect& menu_anchor_rect,
- views::MenuAnchorPosition menu_anchor_position,
- int run_types) {
- DCHECK(!root_);
- DCHECK(model_);
- menu_open_time_ = base::TimeTicks::Now();
- root_ = CreateMenu();
- if (ash::features::IsNotificationsInContextMenuEnabled()) {
- notification_menu_controller_ =
- std::make_unique<NotificationMenuController>(app_id_, root_, this);
- }
- menu_runner_ = std::make_unique<views::MenuRunner>(root_, run_types);
- menu_runner_->RunMenuAt(widget_owner_, nullptr /* MenuButtonController */,
- menu_anchor_rect, menu_anchor_position, source_type_);
- }
- bool AppMenuModelAdapter::IsShowingMenu() const {
- return menu_runner_ && menu_runner_->IsRunning();
- }
- void AppMenuModelAdapter::Cancel() {
- if (!IsShowingMenu())
- return;
- menu_runner_->Cancel();
- }
- int AppMenuModelAdapter::GetCommandIdForHistograms(int command_id) {
- return command_id;
- }
- base::TimeTicks AppMenuModelAdapter::GetClosingEventTime() {
- DCHECK(menu_runner_);
- return menu_runner_->closing_event_time();
- }
- views::Widget* AppMenuModelAdapter::GetSubmenuWidget() {
- if (root_ && root_->GetSubmenu())
- return root_->GetSubmenu()->GetWidget();
- return nullptr;
- }
- void AppMenuModelAdapter::ExecuteCommand(int id, int mouse_event_flags) {
- // Note that the command execution may cause this to get deleted - for
- // example, for search result menus, the command could open an app window
- // causing the app list search to get cleared, destroying non-zero state
- // search results.
- RecordExecuteCommandHistogram(GetCommandIdForHistograms(id));
- views::MenuModelAdapter::ExecuteCommand(id, mouse_event_flags);
- }
- void AppMenuModelAdapter::OnMenuClosed(views::MenuItemView* menu) {
- DCHECK_NE(base::TimeTicks(), menu_open_time_);
- RecordHistogramOnMenuClosed();
- // No |widget_owner_| in tests.
- if (widget_owner_ && widget_owner_->GetRootView()) {
- widget_owner_->GetRootView()->NotifyAccessibilityEvent(
- ax::mojom::Event::kMenuEnd,
- /*send_native_event=*/true);
- }
- if (on_menu_closed_callback_)
- std::move(on_menu_closed_callback_).Run();
- }
- void AppMenuModelAdapter::RecordExecuteCommandHistogram(int command_id) {
- const bool is_not_from_app = app_id().empty();
- base::UmaHistogramSparse(is_not_from_app ? kNonAppContextMenuExecuteCommand
- : kAppContextMenuExecuteCommand,
- command_id);
- if (is_tablet_mode_) {
- base::UmaHistogramSparse(is_not_from_app
- ? kNonAppContextMenuExecuteCommandInTablet
- : kAppContextMenuExecuteCommandInTablet,
- command_id);
- } else {
- base::UmaHistogramSparse(is_not_from_app
- ? kNonAppContextMenuExecuteCommandInClamshell
- : kAppContextMenuExecuteCommandInClamshell,
- command_id);
- }
- }
- } // namespace ash
|