| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_DISPLAY_OVERLAY_CONTROLLER_H_ |
| #define CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_DISPLAY_OVERLAY_CONTROLLER_H_ |
| |
| #include <string> |
| #include <string_view> |
| |
| #include "ash/public/cpp/arc_game_controls_flag.h" |
| #include "ash/public/cpp/window_properties.h" |
| #include "base/memory/raw_ptr.h" |
| #include "chrome/browser/ash/arc/input_overlay/actions/input_element.h" |
| #include "chrome/browser/ash/arc/input_overlay/arc_input_overlay_metrics.h" |
| #include "ui/aura/window_observer.h" |
| #include "ui/compositor/property_change_reason.h" |
| #include "ui/events/event.h" |
| #include "ui/events/event_handler.h" |
| #include "ui/gfx/geometry/point.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/views/widget/unique_widget_ptr.h" |
| |
| namespace views { |
| class View; |
| class Widget; |
| } // namespace views |
| |
| namespace arc::input_overlay { |
| |
| class Action; |
| class ActionEditMenu; |
| class ActionViewListItem; |
| class ButtonOptionsMenu; |
| class DeleteEditShortcut; |
| class EditingList; |
| class InputMappingView; |
| class RichNudge; |
| class TargetView; |
| class TouchInjector; |
| class TouchInjectorObserver; |
| |
| // DisplayOverlayController manages the input mapping view, view and edit mode, |
| // menu, and educational dialog. It also handles the visibility of the |
| // `ActionEditMenu` and `MessageView` by listening to the `LocatedEvent`. |
| class DisplayOverlayController : public ui::EventHandler, |
| public aura::WindowObserver { |
| public: |
| explicit DisplayOverlayController(TouchInjector* touch_injector); |
| DisplayOverlayController(const DisplayOverlayController&) = delete; |
| DisplayOverlayController& operator=(const DisplayOverlayController&) = delete; |
| ~DisplayOverlayController() override; |
| |
| void SetDisplayMode(DisplayMode mode); |
| |
| // Get the bounds of `menu_entry_` in screen coordinates. |
| std::optional<gfx::Rect> GetOverlayMenuEntryBounds(); |
| |
| void OnInputBindingChange(Action* action, |
| std::unique_ptr<InputElement> input_element); |
| |
| // Save changes to actions, without changing the display mode afterward. |
| void SaveToProtoFile(); |
| // Save the changes when users press the save button after editing. |
| void OnCustomizeSave(); |
| const std::string& GetPackageName() const; |
| // Once the menu state is loaded from protobuf data, it should be applied on |
| // the view. For example, `InputMappingView` may not be visible if it is |
| // hidden or input overlay is disabled. |
| void OnApplyMenuState(); |
| // Get window state type. |
| InputOverlayWindowStateType GetWindowStateType() const; |
| |
| // For editor. |
| void AddNewAction(ActionType action_type, const gfx::Point& target_pos); |
| void RemoveAction(Action* action); |
| // Creates a new action with guidance from the reference action, and deletes |
| // the reference action. |
| void ChangeActionType(Action* reference_action_, ActionType type); |
| void RemoveActionNewState(Action* action); |
| |
| // Returns the size of active actions which include the deleted default |
| // actions. |
| size_t GetActiveActionsSize() const; |
| // Returns true if there is only one user added action. |
| bool HasSingleUserAddedAction() const; |
| // Return true if action is not deleted. |
| bool IsActiveAction(Action* action) const; |
| |
| MappingSource GetMappingSource() const; |
| |
| // Add UIs to observer touch injector change. |
| void AddTouchInjectorObserver(TouchInjectorObserver* observer); |
| void RemoveTouchInjectorObserver(TouchInjectorObserver* observer); |
| |
| void AddButtonOptionsMenuWidget(Action* action); |
| void RemoveButtonOptionsMenuWidget(); |
| void SetButtonOptionsMenuWidgetVisibility(bool is_visible); |
| |
| void AddDeleteEditShortcutWidget(ActionViewListItem* anchor_view); |
| void RemoveDeleteEditShortcutWidget(); |
| |
| void EnterButtonPlaceMode(ActionType action_type); |
| // Exits button placement mode after adding a new action if `is_action_added` |
| // is true or giving up by pressing key `esc` if `is_action_added` is false. |
| void ExitButtonPlaceMode(bool is_action_added); |
| void UpdateButtonPlacementNudgeAnchorRect(); |
| |
| void AddActionHighlightWidget(Action* action); |
| void RemoveActionHighlightWidget(); |
| void HideActionHighlightWidget(); |
| // Hides the action highlight if the action highlight is anchored to |
| // `action`'s view. |
| void HideActionHighlightWidgetForAction(Action* action); |
| |
| // `widget` bounds is in screen coordinate. `bounds_in_root_window` is the |
| // window bounds in associated game window's root window. Convert |
| // `bounds_in_root_window` in screen coordinates to set `widget` bounds. |
| void UpdateWidgetBoundsInRootWindow(views::Widget* widget, |
| const gfx::Rect& bounds_in_root_window); |
| |
| ActionViewListItem* GetEditingListItemForAction(Action* action); |
| |
| // ui::EventHandler: |
| void OnMouseEvent(ui::MouseEvent* event) override; |
| void OnTouchEvent(ui::TouchEvent* event) override; |
| void OnKeyEvent(ui::KeyEvent* event) override; |
| |
| // aura::WindowObserver: |
| void OnWindowBoundsChanged(aura::Window* window, |
| const gfx::Rect& old_bounds, |
| const gfx::Rect& new_bounds, |
| ui::PropertyChangeReason reason) override; |
| void OnWindowPropertyChanged(aura::Window* window, |
| const void* key, |
| intptr_t old) override; |
| |
| const TouchInjector* touch_injector() const { return touch_injector_; } |
| |
| private: |
| friend class ActionView; |
| friend class ArcInputOverlayManagerTest; |
| friend class ButtonOptionsMenu; |
| friend class DisplayOverlayControllerTest; |
| friend class EditingList; |
| friend class EditingListTest; |
| friend class EditLabelTest; |
| friend class EducationalView; |
| friend class GameControlsTestBase; |
| friend class InputMappingView; |
| friend class OverlayViewTestBase; |
| friend class RichNudgeTest; |
| |
| // If `on_overlay` is true, set event target on overlay layer. Otherwise, set |
| // event target on the layer underneath the overlay layer. |
| void SetEventTarget(views::Widget* overlay_widget, bool on_overlay); |
| |
| // Update display mode when initializing DisplayOverlayController or the |
| // window property is changed on `ash::kArcGameControlsFlagsKey`. |
| void UpdateDisplayMode(); |
| |
| views::Widget* GetOverlayWidget(); |
| views::View* GetOverlayWidgetContentsView(); |
| bool HasMenuView() const; |
| // Sets input mapping visibility according to `visible` and stores the setting |
| // if `store_visible_state` is true. |
| void SetInputMappingVisible(bool visible, bool store_visible_state = false); |
| bool GetInputMappingViewVisible() const; |
| |
| void SetTouchInjectorEnable(bool enable); |
| bool GetTouchInjectorEnable(); |
| |
| // Close `MessageView` if `LocatedEvent` happens outside |
| // of their view bounds. |
| void ProcessPressedEvent(const ui::LocatedEvent& event); |
| |
| // When the input is processed on overlay in edit mode, PlaceholderActivity |
| // task window becomes the front task window. This ensures the target task |
| // window is moved back to the front of task stack on ARC side for view mode. |
| void EnsureTaskWindowToFrontForViewMode(views::Widget* overlay_widget); |
| |
| void UpdateForBoundsChanged(); |
| |
| // For beta. |
| void RemoveAllWidgets(); |
| |
| void AddInputMappingWidget(); |
| void RemoveInputMappingWidget(); |
| InputMappingView* GetInputMapping(); |
| |
| // Stacks input mapping at the bottom and under the game dashboard UIs. |
| void StackInputMappingAtBottomForViewMode(); |
| |
| void AddEditingListWidget(); |
| void RemoveEditingListWidget(); |
| void SetEditingListVisibility(bool visible); |
| EditingList* GetEditingList(); |
| |
| ButtonOptionsMenu* GetButtonOptionsMenu(); |
| |
| // Shows or removes target view when in or out button place mode. |
| void AddTargetWidget(ActionType action_type); |
| void RemoveTargetWidget(); |
| TargetView* GetTargetView() const; |
| |
| void AddRichNudge(); |
| void RemoveRichNudge(); |
| RichNudge* GetRichNudge() const; |
| |
| DeleteEditShortcut* GetDeleteEditShortcut() const; |
| |
| // Update widget bounds if the view content is changed or the app window |
| // bounds are changed. |
| void UpdateButtonOptionsMenuWidgetBounds(); |
| void UpdateInputMappingWidgetBounds(); |
| void UpdateEditingListWidgetBounds(); |
| void UpdateTargetWidgetBounds(); |
| |
| // `TouchInjector` only rewrite events in `kView` mode. When changing between |
| // edit mode and view mode or the feature is disabled from menu or if the game |
| // dashboard menu shows up, it needs to tell `TouchInjector` if it can rewrite |
| // events. |
| void UpdateEventRewriteCapability(); |
| |
| // Returns a list of visible widgets that are available to be traversed in the |
| // edit mode. |
| std::vector<views::Widget*> GetTraversableWidgets() const; |
| |
| void MaybeChangeFocusWidget(ui::KeyEvent& event); |
| |
| // Owned by `ArcInputOverlayManager`. |
| const raw_ptr<TouchInjector> touch_injector_; |
| |
| DisplayMode display_mode_ = DisplayMode::kNone; |
| |
| // For beta. |
| std::unique_ptr<views::Widget> input_mapping_widget_; |
| std::unique_ptr<views::Widget> editing_list_widget_; |
| std::unique_ptr<views::Widget> button_options_widget_; |
| std::unique_ptr<views::Widget> target_widget_; |
| std::unique_ptr<views::Widget> action_highlight_widget_; |
| views::UniqueWidgetPtr delete_edit_shortcut_widget_; |
| views::UniqueWidgetPtr rich_nudge_widget_; |
| }; |
| |
| } // namespace arc::input_overlay |
| |
| #endif // CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_DISPLAY_OVERLAY_CONTROLLER_H_ |