Skip to content

Commit

Permalink
gd: Implement Game Controls button functions
Browse files Browse the repository at this point in the history
This CL adds logic for Game Controls buttons.
- If Game Controls is disabled by the feature tile button, the details
  row will be disabled and the hint switch is disabled and switched off
  if there is.
- If Game Controls is enabled, the details row will be enabled and the
  hint hint switch is enabled. The hint switch state depends on the
  flag.
- Once the "Set up" button or details row button is pressed, it enters
  into Game Controls edit mode and closes the menu.
- If the Game Controls tile on the main menu is toggled on/off, the
  quick toolbar should get updated to the main menu.
- The main menu doesn't need to update if the quick toolbar button is
  toggled on/off, because the main menu is expected to close when
  the input is outside of the main menu.

Bug: b/275380943
Test: unit test
Change-Id: I33b233dd50ace6fefaed77e0a33977d508f59e85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4662649
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Cici Ruan <cuicuiruan@google.com>
Auto-Submit: Cici Ruan <cuicuiruan@google.com>
Cr-Commit-Position: refs/heads/main@{#1170275}
  • Loading branch information
Cici Ruan authored and Chromium LUCI CQ committed Jul 14, 2023
1 parent 8983b7b commit a77d713
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 36 deletions.
100 changes: 100 additions & 0 deletions ash/game_dashboard/game_dashboard_context_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ash/game_dashboard/game_dashboard_controller.h"
#include "ash/game_dashboard/game_dashboard_test_base.h"
#include "ash/game_dashboard/game_dashboard_toolbar_view.h"
#include "ash/game_dashboard/game_dashboard_utils.h"
#include "ash/game_dashboard/test_game_dashboard_delegate.h"
#include "ash/public/cpp/ash_view_ids.h"
#include "ash/public/cpp/capture_mode/capture_mode_test_api.h"
Expand Down Expand Up @@ -252,6 +253,105 @@ TEST_F(GameDashboardContextTest, GameControlsMenuState) {
/*setup_states=*/false);
}

// Verifies Game Controls button logics.
TEST_F(GameDashboardContextTest, GameControlsMenuFunctions) {
CreateGameWindow(/*is_arc_window=*/true);
// Game controls is available, not empty, enabled and hint on.
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kMenu));

// Open the main menu and disable Game Controls.
auto* menu_button = GetMainMenuButtonWidget()->GetContentsView();
LeftClickOn(menu_button);
EXPECT_TRUE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kMenu));

// Open the quick toolbar.
LeftClickOn(GetMainMenuViewById(VIEW_ID_GD_TOOLBAR_TILE));
auto* toolbar_button = GetToolbarGameControlsButton();

auto* tile =
static_cast<FeatureTile*>(GetMainMenuViewById(VIEW_ID_GD_CONTROLS_TILE));
auto* detail_row = GetMainMenuViewById(VIEW_ID_GD_CONTROLS_DETAILS_ROW);
auto* switch_button = static_cast<Switch*>(
GetMainMenuViewById(VIEW_ID_GD_CONTROLS_HINT_SWITCH));
EXPECT_TRUE(detail_row->GetEnabled());
EXPECT_TRUE(switch_button->GetEnabled());
EXPECT_TRUE(switch_button->GetIsOn());
EXPECT_TRUE(toolbar_button->GetEnabled());
EXPECT_TRUE(toolbar_button->toggled());
// Disable Game Controls.
LeftClickOn(tile);
EXPECT_FALSE(detail_row->GetEnabled());
EXPECT_FALSE(switch_button->GetEnabled());
EXPECT_FALSE(switch_button->GetIsOn());
// Toolbar button should also get updated.
EXPECT_TRUE(toolbar_button->GetEnabled());
EXPECT_FALSE(toolbar_button->toggled());

EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kEnabled));

// Close the quick toolbar.
LeftClickOn(GetMainMenuViewById(VIEW_ID_GD_TOOLBAR_TILE));

// Close the main menu.
LeftClickOn(menu_button);
EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kMenu));

// Open the main menu again to check if the states are preserved and close it.
OpenMenuCheckGameControlsUIState(
/*tile_states=*/{/*expect_exists=*/true, /*expect_enabled=*/true,
/*expect_toggled=*/false},
/*details_row_states=*/{/*expect_exists=*/true, /*expect_enabled=*/false},
/*hint_states=*/
{/*expect_exists=*/true, /*expect_enabled=*/false, /*expect_on=*/false},
/*setup_exists=*/false);

// Open the main menu, enable Game Controls and switch hint button off.
LeftClickOn(menu_button);
tile =
static_cast<FeatureTile*>(GetMainMenuViewById(VIEW_ID_GD_CONTROLS_TILE));
detail_row = GetMainMenuViewById(VIEW_ID_GD_CONTROLS_DETAILS_ROW);
switch_button = static_cast<Switch*>(
GetMainMenuViewById(VIEW_ID_GD_CONTROLS_HINT_SWITCH));
// Open the quick toolbar.
LeftClickOn(GetMainMenuViewById(VIEW_ID_GD_TOOLBAR_TILE));
toolbar_button = GetToolbarGameControlsButton();
// Enable Game Controls.
LeftClickOn(tile);
EXPECT_TRUE(detail_row->GetEnabled());
EXPECT_TRUE(switch_button->GetEnabled());
EXPECT_TRUE(switch_button->GetIsOn());
EXPECT_TRUE(toolbar_button->GetEnabled());
EXPECT_TRUE(toolbar_button->toggled());
// Switch hint off.
LeftClickOn(switch_button);
EXPECT_FALSE(switch_button->GetIsOn());
// Close the quick toolbar and main menu.
LeftClickOn(GetMainMenuViewById(VIEW_ID_GD_TOOLBAR_TILE));
LeftClickOn(menu_button);

// Open the main menu again to check if the states are preserved and close it.
OpenMenuCheckGameControlsUIState(
/*tile_states=*/{/*expect_exists=*/true, /*expect_enabled=*/true,
/*expect_toggled=*/true},
/*details_row_states=*/{/*expect_exists=*/true, /*expect_enabled=*/true},
/*hint_states=*/
{/*expect_exists=*/true, /*expect_enabled=*/true, /*expect_on=*/false},
/*setup_exists=*/false);
}

// -----------------------------------------------------------------------------
// GameTypeGameDashboardContextTest:
// Test fixture to test both ARC and GeForceNow game window depending on the
Expand Down
111 changes: 84 additions & 27 deletions ash/game_dashboard/game_dashboard_main_menu_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,19 +256,49 @@ void GameDashboardMainMenuView::OnScreenshotTilePressed() {
}

void GameDashboardMainMenuView::OnGameControlsTilePressed() {
// TODO(b/275380943): Add support when controls tile is pressed.
game_controls_tile_->SetToggled(!game_controls_tile_->IsToggled());

bool is_toggled = game_controls_tile_->IsToggled();
// TODO(b/274690042): Replace the strings with localized strings.
game_controls_details_->SetSubtitle(is_toggled ? u"On" : u"Off");
game_controls_details_->SetEnabled(is_toggled);

if (game_controls_setup_button_) {
game_controls_setup_button_->SetEnabled(is_toggled);
} else {
DCHECK(game_controls_hint_switch_);
game_controls_hint_switch_->SetEnabled(is_toggled);
game_controls_hint_switch_->SetIsOn(is_toggled);
}

auto* game_window = context_->game_window();
game_window->SetProperty(
kArcGameControlsFlagsKey,
game_dashboard_utils::UpdateFlag(
game_window->GetProperty(kArcGameControlsFlagsKey),
static_cast<ArcGameControlsFlag>(ArcGameControlsFlag::kEnabled |
ArcGameControlsFlag::kHint),
/*enable_flag=*/is_toggled));
}

void GameDashboardMainMenuView::OnGameControlsDetailsPressed() {
// TODO(b/275380943): Implement the function.
EnableGameControlsEditMode();
GetWidget()->Close();
}

void GameDashboardMainMenuView::OnGameControlsSetUpButtonPressed() {
// TODO(b/275380943): Implement the function.
EnableGameControlsEditMode();
GetWidget()->Close();
}

void GameDashboardMainMenuView::OnGameControlsHintSwitchButtonPressed() {
// TODO(b/275380943): Implement the function.
auto* game_window = context_->game_window();
game_window->SetProperty(
kArcGameControlsFlagsKey,
game_dashboard_utils::UpdateFlag(
game_window->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kHint,
/*enable_flag=*/game_controls_hint_switch_->GetIsOn()));
}

void GameDashboardMainMenuView::OnScreenSizeSettingsButtonPressed() {
Expand Down Expand Up @@ -343,18 +373,18 @@ void GameDashboardMainMenuView::MaybeAddGameControlsTile(
return;
}

auto* controls_tile = container->AddChildView(CreateTile(
game_controls_tile_ = container->AddChildView(CreateTile(
base::BindRepeating(&GameDashboardMainMenuView::OnGameControlsTilePressed,
base::Unretained(this)),
/*is_togglable=*/true, FeatureTile::TileType::kCompact,
VIEW_ID_GD_CONTROLS_TILE, kGdGameControlsIcon,
l10n_util::GetStringUTF16(
IDS_ASH_GAME_DASHBOARD_CONTROLS_TILE_BUTTON_TITLE)));

controls_tile->SetEnabled(
game_controls_tile_->SetEnabled(
!game_dashboard_utils::IsFlagSet(*flags, ArcGameControlsFlag::kEmpty));
if (controls_tile->GetEnabled()) {
controls_tile->SetToggled(
if (game_controls_tile_->GetEnabled()) {
game_controls_tile_->SetToggled(
game_dashboard_utils::IsFlagSet(*flags, ArcGameControlsFlag::kEnabled));
}
}
Expand All @@ -367,7 +397,8 @@ void GameDashboardMainMenuView::MaybeAddGameControlsDetailsRow(
return;
}

auto* game_controls_details =
DCHECK(game_controls_tile_);
game_controls_details_ =
container->AddChildView(std::make_unique<FeatureDetailsRow>(
base::BindRepeating(
&GameDashboardMainMenuView::OnGameControlsDetailsPressed,
Expand All @@ -377,32 +408,32 @@ void GameDashboardMainMenuView::MaybeAddGameControlsDetailsRow(
/*icon=*/kGdGameControlsIcon, /*title=*/
l10n_util::GetStringUTF16(
IDS_ASH_GAME_DASHBOARD_CONTROLS_TILE_BUTTON_TITLE)));
game_controls_details->SetID(VIEW_ID_GD_CONTROLS_DETAILS_ROW);
game_controls_details_->SetID(VIEW_ID_GD_CONTROLS_DETAILS_ROW);

const bool is_enabled =
game_dashboard_utils::IsFlagSet(*flags, ArcGameControlsFlag::kEnabled);
// TODO(b/279117180): Include application name in the subtitle.
// TODO(b/274690042): Replace the strings with localized strings.
game_controls_details->SetSubtitle(is_enabled ? u"On" : u"Off");
game_controls_details->SetEnabled(is_enabled);
game_controls_details_->SetSubtitle(is_enabled ? u"On" : u"Off");
game_controls_details_->SetEnabled(is_enabled);

if (game_dashboard_utils::IsFlagSet(*flags, ArcGameControlsFlag::kEmpty)) {
// Add "Set up" button for empty state.
// TODO(b/274690042): Replace the strings with localized strings.
auto* setup_button = game_controls_details->AddCustomizedTailView(
game_controls_setup_button_ = game_controls_details_->AddCustomizedTailView(
std::make_unique<PillButton>(
base::BindRepeating(
&GameDashboardMainMenuView::OnGameControlsSetUpButtonPressed,
base::Unretained(this)),
u"Set up", PillButton::Type::kPrimaryWithoutIcon,
/*icon=*/nullptr));
setup_button->SetID(VIEW_ID_GD_CONTROLS_SETUP_BUTTON);
setup_button->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, 20, 0, 0));
setup_button->SetEnabled(is_enabled);
game_controls_setup_button_->SetID(VIEW_ID_GD_CONTROLS_SETUP_BUTTON);
game_controls_setup_button_->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, 20, 0, 0));
game_controls_setup_button_->SetEnabled(is_enabled);
} else {
// Add toggle button and arrow icon for non-empty state.
auto* edit_container = game_controls_details->AddCustomizedTailView(
auto* edit_container = game_controls_details_->AddCustomizedTailView(
std::make_unique<views::View>());
edit_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
Expand All @@ -412,20 +443,21 @@ void GameDashboardMainMenuView::MaybeAddGameControlsDetailsRow(
gfx::Insets::TLBR(0, 8, 0, 0));

// Add switch_button to show or hide input mapping hints.
auto* switch_button = edit_container->AddChildView(
game_controls_hint_switch_ = edit_container->AddChildView(
std::make_unique<Switch>(base::BindRepeating(
&GameDashboardMainMenuView::OnGameControlsHintSwitchButtonPressed,
base::Unretained(this))));
switch_button->SetID(VIEW_ID_GD_CONTROLS_HINT_SWITCH);
game_controls_hint_switch_->SetID(VIEW_ID_GD_CONTROLS_HINT_SWITCH);
// TODO(b/279117180): Update the accessibility name.
switch_button->SetAccessibleName(
game_controls_hint_switch_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_LIST_FOLDER_NAME_PLACEHOLDER));
switch_button->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, 0, 0, 18));
switch_button->SetEnabled(is_enabled);
switch_button->SetIsOn(is_enabled ? game_dashboard_utils::IsFlagSet(
*flags, ArcGameControlsFlag::kHint)
: false);
game_controls_hint_switch_->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, 0, 0, 18));
game_controls_hint_switch_->SetEnabled(is_enabled);
game_controls_hint_switch_->SetIsOn(
is_enabled ? game_dashboard_utils::IsFlagSet(*flags,
ArcGameControlsFlag::kHint)
: false);
// Add arrow icon.
edit_container->AddChildView(
std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
Expand Down Expand Up @@ -481,6 +513,31 @@ void GameDashboardMainMenuView::AddUtilityClusterRow() {
l10n_util::GetStringUTF16(IDS_ASH_GAME_DASHBOARD_SETTINGS_TOOLTIP)));
}

void GameDashboardMainMenuView::EnableGameControlsEditMode() {
auto* game_window = context_->game_window();
game_window->SetProperty(
kArcGameControlsFlagsKey,
game_dashboard_utils::UpdateFlag(
game_window->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kEdit, /*enable_flag=*/true));
}

void GameDashboardMainMenuView::VisibilityChanged(views::View* starting_from,
bool is_visible) {
// When the menu shows up, Game Controls shouldn't rewrite events. So Game
// Controls needs to know when the menu is open or closed.
auto flags =
game_dashboard_utils::GetGameControlsFlag(context_->game_window());
if (!flags) {
return;
}

context_->game_window()->SetProperty(
kArcGameControlsFlagsKey,
game_dashboard_utils::UpdateFlag(*flags, ArcGameControlsFlag::kMenu,
/*enable_flag=*/is_visible));
}

BEGIN_METADATA(GameDashboardMainMenuView, views::BubbleDialogDelegateView)
END_METADATA

Expand Down
15 changes: 14 additions & 1 deletion ash/game_dashboard/game_dashboard_main_menu_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
#ifndef ASH_GAME_DASHBOARD_GAME_DASHBOARD_MAIN_MENU_VIEW_H_
#define ASH_GAME_DASHBOARD_GAME_DASHBOARD_MAIN_MENU_VIEW_H_

#include "ash/public/cpp/arc_game_controls_flag.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"

namespace ash {

class FeatureTile;
class GameDashboardContext;
class PillButton;
class Switch;

// GameDashboardMainMenuView is the expanded menu view attached to the game
// dashboard button.
Expand Down Expand Up @@ -78,8 +80,19 @@ class GameDashboardMainMenuView : public views::BubbleDialogDelegateView {
// buttons) to the Game Controls tile view.
void AddUtilityClusterRow();

// Enables Game Controls edit mode.
void EnableGameControlsEditMode();

// views::View:
void VisibilityChanged(views::View* starting_from, bool is_visible) override;

// Allows this class to access `GameDashboardContext` owned functions/objects.
const raw_ptr<GameDashboardContext, ExperimentalAsh> context_;

raw_ptr<FeatureTile> game_controls_tile_ = nullptr;
raw_ptr<FeatureDetailsRow> game_controls_details_ = nullptr;
raw_ptr<PillButton> game_controls_setup_button_ = nullptr;
raw_ptr<Switch> game_controls_hint_switch_ = nullptr;
};

} // namespace ash
Expand Down
Loading

0 comments on commit a77d713

Please sign in to comment.