blob: 38c578f11b277299718f4869ecbeafb19785c8a4 [file] [log] [blame]
// Copyright 2017 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/shelf/shelf_context_menu_model.h"
#include <memory>
#include <string>
#include <utility>
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/app_list/app_list_metrics.h"
#include "ash/public/cpp/app_menu_constants.h"
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/public/cpp/shelf_item_delegate.h"
#include "ash/public/cpp/shelf_model.h"
#include "ash/public/cpp/shelf_prefs.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/wallpaper/wallpaper_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/metrics/user_metrics.h"
#include "base/numerics/safe_conversions.h"
#include "components/prefs/pref_service.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/menu/menu_config.h"
namespace ash {
namespace {
// Returns true if the user can modify the shelf's auto-hide behavior pref.
bool CanUserModifyShelfAutoHide(PrefService* prefs) {
return prefs && prefs->FindPreference(prefs::kShelfAutoHideBehaviorLocal)
->IsUserModifiable();
}
// Returns true if the display is showing a fullscreen window.
// NOTE: This duplicates the functionality of Chrome's IsFullScreenMode.
bool IsFullScreenMode(int64_t display_id) {
auto* controller = Shell::GetRootWindowControllerWithDisplayId(display_id);
return controller && controller->GetWindowForFullscreenMode();
}
// Create a vector icon with the correct size and color for the menu.
gfx::ImageSkia GetIcon(const gfx::VectorIcon& icon) {
const views::MenuConfig& menu_config = views::MenuConfig::instance();
return gfx::CreateVectorIcon(icon, menu_config.touchable_icon_size,
menu_config.touchable_icon_color);
}
} // namespace
ShelfContextMenuModel::ShelfContextMenuModel(ShelfItemDelegate* delegate,
int64_t display_id)
: ui::SimpleMenuModel(this), delegate_(delegate), display_id_(display_id) {
// Add shelf and wallpaper items if ShelfView or AppListButton are selected.
if (!delegate || delegate_->app_id() == kAppListId)
AddShelfAndWallpaperItems();
}
ShelfContextMenuModel::~ShelfContextMenuModel() = default;
bool ShelfContextMenuModel::IsCommandIdChecked(int command_id) const {
if (command_id == MENU_ALIGNMENT_LEFT ||
command_id == MENU_ALIGNMENT_BOTTOM ||
command_id == MENU_ALIGNMENT_RIGHT) {
PrefService* prefs =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
const ShelfAlignment alignment = GetShelfAlignmentPref(prefs, display_id_);
if (command_id == MENU_ALIGNMENT_LEFT)
return alignment == SHELF_ALIGNMENT_LEFT;
if (command_id == MENU_ALIGNMENT_BOTTOM) {
return alignment == SHELF_ALIGNMENT_BOTTOM ||
alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED;
}
if (command_id == MENU_ALIGNMENT_RIGHT)
return alignment == SHELF_ALIGNMENT_RIGHT;
}
return SimpleMenuModel::Delegate::IsCommandIdChecked(command_id);
}
void ShelfContextMenuModel::ExecuteCommand(int command_id, int event_flags) {
DCHECK(IsCommandIdEnabled(command_id));
Shell* shell = Shell::Get();
PrefService* prefs =
shell->session_controller()->GetLastActiveUserPrefService();
if (!prefs) // Null during startup.
return;
UserMetricsRecorder* metrics = shell->metrics();
// Clamshell mode only options should not activate in tablet mode.
const bool is_tablet_mode =
shell->tablet_mode_controller()->IsTabletModeWindowManagerEnabled();
switch (command_id) {
case MENU_AUTO_HIDE:
SetShelfAutoHideBehaviorPref(
prefs, display_id_,
GetShelfAutoHideBehaviorPref(prefs, display_id_) ==
SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS
? SHELF_AUTO_HIDE_BEHAVIOR_NEVER
: SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
break;
case MENU_ALIGNMENT_LEFT:
DCHECK(!is_tablet_mode);
metrics->RecordUserMetricsAction(UMA_SHELF_ALIGNMENT_SET_LEFT);
SetShelfAlignmentPref(prefs, display_id_, SHELF_ALIGNMENT_LEFT);
break;
case MENU_ALIGNMENT_RIGHT:
DCHECK(!is_tablet_mode);
metrics->RecordUserMetricsAction(UMA_SHELF_ALIGNMENT_SET_RIGHT);
SetShelfAlignmentPref(prefs, display_id_, SHELF_ALIGNMENT_RIGHT);
break;
case MENU_ALIGNMENT_BOTTOM:
DCHECK(!is_tablet_mode);
metrics->RecordUserMetricsAction(UMA_SHELF_ALIGNMENT_SET_BOTTOM);
SetShelfAlignmentPref(prefs, display_id_, SHELF_ALIGNMENT_BOTTOM);
break;
case MENU_CHANGE_WALLPAPER:
shell->wallpaper_controller()->OpenWallpaperPickerIfAllowed();
break;
default:
if (delegate_) {
if (app_list::IsCommandIdAnAppLaunch(command_id) &&
shell->app_list_controller()) {
shell->app_list_controller()->RecordShelfAppLaunched(
base::nullopt /* recorded_app_list_view_state */,
base::nullopt /* recorded_home_launcher_shown */);
}
delegate_->ExecuteCommand(true, command_id, event_flags, display_id_);
}
break;
}
}
void ShelfContextMenuModel::AddShelfAndWallpaperItems() {
PrefService* prefs =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
if (!prefs) // Null during startup.
return;
// In fullscreen, the shelf is either hidden or auto-hidden, depending on the
// type of fullscreen. Do not show the auto-hide menu item while in fullscreen
// because it is confusing when the preference appears not to apply.
if (CanUserModifyShelfAutoHide(prefs) && !IsFullScreenMode(display_id_)) {
const bool is_autohide_set =
GetShelfAutoHideBehaviorPref(prefs, display_id_) ==
SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
auto string_id = is_autohide_set
? IDS_ASH_SHELF_CONTEXT_MENU_ALWAYS_SHOW_SHELF
: IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE;
auto icon = GetIcon(is_autohide_set ? kAlwaysShowShelfIcon : kAutoHideIcon);
AddItemWithStringIdAndIcon(MENU_AUTO_HIDE, string_id, icon);
}
// Only allow shelf alignment modifications by the owner or user. In tablet
// mode, the shelf alignment option is not shown.
LoginStatus status = Shell::Get()->session_controller()->login_status();
if ((status == LoginStatus::USER || status == LoginStatus::OWNER) &&
!Shell::Get()
->tablet_mode_controller()
->IsTabletModeWindowManagerEnabled()) {
alignment_submenu_ = std::make_unique<ui::SimpleMenuModel>(this);
constexpr int group = 0;
alignment_submenu_->AddRadioItemWithStringId(
MENU_ALIGNMENT_LEFT, IDS_ASH_SHELF_CONTEXT_MENU_ALIGN_LEFT, group);
alignment_submenu_->AddRadioItemWithStringId(
MENU_ALIGNMENT_BOTTOM, IDS_ASH_SHELF_CONTEXT_MENU_ALIGN_BOTTOM, group);
alignment_submenu_->AddRadioItemWithStringId(
MENU_ALIGNMENT_RIGHT, IDS_ASH_SHELF_CONTEXT_MENU_ALIGN_RIGHT, group);
AddSubMenuWithStringIdAndIcon(
MENU_ALIGNMENT_MENU, IDS_ASH_SHELF_CONTEXT_MENU_POSITION,
alignment_submenu_.get(), GetIcon(kShelfPositionIcon));
}
if (Shell::Get()->wallpaper_controller()->CanOpenWallpaperPicker()) {
AddItemWithStringIdAndIcon(MENU_CHANGE_WALLPAPER,
IDS_AURA_SET_DESKTOP_WALLPAPER,
GetIcon(kWallpaperIcon));
}
}
} // namespace ash