| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/game_dashboard/game_dashboard_utils.h" |
| |
| #include "ash/constants/ash_pref_names.h" |
| #include "ash/public/cpp/app_types_util.h" |
| #include "ash/public/cpp/window_properties.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shell.h" |
| #include "ash/strings/grit/ash_strings.h" |
| #include "ash/style/icon_button.h" |
| #include "ash/system/unified/feature_tile.h" |
| #include "ash/wm/overview/overview_controller.h" |
| #include "chromeos/ui/frame/frame_header.h" |
| #include "components/prefs/pref_service.h" |
| #include "ui/aura/window.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/display/screen.h" |
| #include "ui/views/accessibility/view_accessibility.h" |
| #include "ui/views/controls/button/button.h" |
| #include "ui/views/view_utils.h" |
| |
| namespace ash::game_dashboard_utils { |
| |
| bool IsFlagSet(ArcGameControlsFlag flags, ArcGameControlsFlag flag) { |
| return (flags & flag) == flag; |
| } |
| |
| bool IsFlagChanged(ArcGameControlsFlag new_flags, |
| ArcGameControlsFlag old_flags, |
| ArcGameControlsFlag flag) { |
| return ((new_flags ^ old_flags) & flag) == flag; |
| } |
| |
| ArcGameControlsFlag UpdateFlag(ArcGameControlsFlag flags, |
| ArcGameControlsFlag flag, |
| bool enable_flag) { |
| return static_cast<ArcGameControlsFlag>(enable_flag ? flags | flag |
| : flags & ~flag); |
| } |
| |
| bool ShouldEnableFeatures() { |
| return !OverviewController::Get()->InOverviewSession() && |
| !display::Screen::GetScreen()->InTabletMode(); |
| } |
| |
| views::Widget* GetNextWidgetToFocus( |
| const std::vector<views::Widget*>& widget_list, |
| const views::Widget* focused_widget, |
| bool reverse) { |
| if (auto it = |
| std::find(widget_list.begin(), widget_list.end(), focused_widget); |
| it != widget_list.end()) { |
| const int focused_widget_index = |
| std::distance(widget_list.begin(), |
| it); // it - widget_list_.begin(); |
| const size_t widget_list_size = widget_list.size(); |
| const size_t next_focus_widget_index = |
| (reverse ? (focused_widget_index + widget_list_size - 1u) |
| : (focused_widget_index + 1u)) % |
| widget_list_size; |
| return widget_list[next_focus_widget_index]; |
| } |
| return nullptr; |
| } |
| |
| std::optional<ArcGameControlsFlag> GetGameControlsFlag( |
| const aura::Window* window) { |
| if (!IsArcWindow(window)) { |
| return std::nullopt; |
| } |
| |
| ArcGameControlsFlag flags = window->GetProperty(kArcGameControlsFlagsKey); |
| CHECK(IsFlagSet(flags, ArcGameControlsFlag::kKnown)); |
| return std::make_optional<ArcGameControlsFlag>(flags); |
| } |
| |
| void UpdateGameControlsHintButton(views::Button* button, |
| ArcGameControlsFlag flags) { |
| CHECK(button); |
| |
| // Update button enabled state, toggle state, and sub-label if it is needed. |
| DCHECK(IsFlagSet(flags, ArcGameControlsFlag::kKnown)); |
| const bool is_available = IsFlagSet(flags, ArcGameControlsFlag::kAvailable); |
| const bool is_enabled = IsFlagSet(flags, ArcGameControlsFlag::kEnabled); |
| const bool is_empty = IsFlagSet(flags, ArcGameControlsFlag::kEmpty); |
| const bool is_hint_on = IsFlagSet(flags, ArcGameControlsFlag::kHint); |
| |
| const bool should_enable = is_available && is_enabled && !is_empty; |
| const bool should_toggle = should_enable && is_hint_on; |
| if (auto* feature_tile = views::AsViewClass<FeatureTile>(button)) { |
| feature_tile->SetEnabled(should_enable); |
| feature_tile->SetToggled(should_toggle); |
| feature_tile->SetSubLabel(l10n_util::GetStringUTF16( |
| should_enable ? (should_toggle ? IDS_ASH_GAME_DASHBOARD_GC_TILE_VISIBLE |
| : IDS_ASH_GAME_DASHBOARD_GC_TILE_HIDDEN) |
| : IDS_ASH_GAME_DASHBOARD_GC_TILE_OFF)); |
| } else { |
| auto* icon_button = views::AsViewClass<IconButton>(button); |
| CHECK(icon_button); |
| icon_button->SetEnabled(should_enable); |
| icon_button->SetToggled(should_toggle); |
| } |
| |
| // Update tooltip text. |
| int tooltip_text_id; |
| if (!is_available) { |
| // TODO(b/274690042): Replace it with a different tooltip text once it's |
| // ready. |
| tooltip_text_id = IDS_ASH_GAME_DASHBOARD_GC_TILE_TOOLTIPS_NOT_AVAILABLE; |
| } else if (is_enabled) { |
| if (is_empty) { |
| tooltip_text_id = IDS_ASH_GAME_DASHBOARD_GC_TILE_TOOLTIPS_NOT_SETUP; |
| } else if (is_hint_on) { |
| tooltip_text_id = IDS_ASH_GAME_DASHBOARD_GC_TILE_TOOLTIPS_HIDE_CONTROLS; |
| } else { |
| tooltip_text_id = IDS_ASH_GAME_DASHBOARD_GC_TILE_TOOLTIPS_SHOW_CONTROLS; |
| } |
| } else { |
| tooltip_text_id = IDS_ASH_GAME_DASHBOARD_GC_TILE_TOOLTIPS_NOT_AVAILABLE; |
| } |
| button->SetTooltipText(l10n_util::GetStringUTF16(tooltip_text_id)); |
| } |
| |
| bool ShouldEnableGameDashboardButton(aura::Window* window) { |
| if (!IsArcWindow(window)) { |
| return true; |
| } |
| |
| const auto flags = window->GetProperty(kArcGameControlsFlagsKey); |
| return IsFlagSet(flags, ArcGameControlsFlag::kKnown) && |
| !IsFlagSet(flags, ArcGameControlsFlag::kEdit); |
| } |
| |
| bool ShouldShowWelcomeDialog() { |
| PrefService* prefs = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| DCHECK(prefs) << "A valid PrefService is needed to determine whether to show " |
| "the welcome dialog."; |
| return prefs->GetBoolean(prefs::kGameDashboardShowWelcomeDialog); |
| } |
| |
| void SetShowWelcomeDialog(bool show_dialog) { |
| PrefService* prefs = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| DCHECK(prefs) << "A valid PrefService is needed to update the show welcome " |
| "dialog param."; |
| prefs->SetBoolean(prefs::kGameDashboardShowWelcomeDialog, show_dialog); |
| } |
| |
| bool ShouldShowToolbar() { |
| PrefService* prefs = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| DCHECK(prefs) << "A valid PrefService is needed to determine whether to show " |
| "the toolbar."; |
| return prefs->GetBoolean(prefs::kGameDashboardShowToolbar); |
| } |
| |
| void SetShowToolbar(bool show_toolbar) { |
| PrefService* prefs = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| DCHECK(prefs) << "A valid PrefService is needed to update the show toolbar " |
| "param."; |
| prefs->SetBoolean(prefs::kGameDashboardShowToolbar, show_toolbar); |
| } |
| |
| int GetFrameHeaderHeight(aura::Window* window) { |
| CHECK(window); |
| auto* frame_header = chromeos::FrameHeader::Get( |
| views::Widget::GetWidgetForNativeWindow(window)); |
| return (frame_header && frame_header->view()->GetVisible()) |
| ? frame_header->GetHeaderHeight() |
| : 0; |
| } |
| |
| void UpdateAccessibilityTree(const std::vector<views::Widget*>& widget_list) { |
| const size_t widget_list_size = widget_list.size(); |
| if (widget_list_size <= 1u) { |
| return; |
| } |
| |
| for (size_t i = 0; i < widget_list_size; i++) { |
| auto* contents_view = widget_list[i]->GetContentsView(); |
| auto& view_a11y = contents_view->GetViewAccessibility(); |
| const size_t prev_index = (i + widget_list_size - 1u) % widget_list_size; |
| const size_t next_index = (i + 1u) % widget_list_size; |
| |
| view_a11y.SetPreviousFocus(widget_list[prev_index]); |
| view_a11y.SetNextFocus(widget_list[next_index]); |
| contents_view->NotifyAccessibilityEventDeprecated( |
| ax::mojom::Event::kTreeChanged, |
| /*send_native_event=*/true); |
| } |
| } |
| |
| } // namespace ash::game_dashboard_utils |