| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef UI_VIEWS_TEST_MENU_TEST_UTILS_H_ |
| #define UI_VIEWS_TEST_MENU_TEST_UTILS_H_ |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "ui/base/mojom/menu_source_type.mojom-forward.h" |
| #include "ui/compositor/layer_tree_owner.h" |
| #include "ui/views/controls/menu/menu_delegate.h" |
| #include "ui/views/test/test_views_delegate.h" |
| #include "ui/views/view.h" |
| |
| namespace views { |
| |
| class MenuController; |
| |
| namespace test { |
| |
| // Test implementation of MenuDelegate that tracks calls to MenuDelegate, along |
| // with the provided parameters. |
| class TestMenuDelegate : public MenuDelegate { |
| public: |
| // Special value for `execute_command_id()` used if a command was never |
| // executed. |
| static constexpr int kInvalidExecuteCommandId = 0; |
| |
| TestMenuDelegate(); |
| |
| TestMenuDelegate(const TestMenuDelegate&) = delete; |
| TestMenuDelegate& operator=(const TestMenuDelegate&) = delete; |
| |
| ~TestMenuDelegate() override; |
| |
| int show_context_menu_count() const { return show_context_menu_count_; } |
| MenuItemView* show_context_menu_source() { return show_context_menu_source_; } |
| int execute_command_id() const { return execute_command_id_; } |
| int on_menu_closed_called() const { return on_menu_closed_called_count_; } |
| MenuItemView* on_menu_closed_menu() const { return on_menu_closed_menu_; } |
| bool is_drop_performed() const { return is_drop_performed_; } |
| int will_hide_menu_count() const { return will_hide_menu_count_; } |
| MenuItemView* will_hide_menu() { return will_hide_menu_; } |
| void set_should_execute_command_without_closing_menu(bool val) { |
| should_execute_command_without_closing_menu_ = val; |
| } |
| void set_should_close_on_drag_complete(bool val) { |
| should_close_on_drag_complete_ = val; |
| } |
| |
| // `ShowContextMenu()` will return false for the provided `command_id`. |
| void DisableContextMenuForCommandId(int command_id); |
| |
| // MenuDelegate: |
| bool ShowContextMenu(MenuItemView* source, |
| int id, |
| const gfx::Point& p, |
| ui::mojom::MenuSourceType source_type) override; |
| void ExecuteCommand(int id) override; |
| void OnMenuClosed(MenuItemView* menu) override; |
| views::View::DropCallback GetDropCallback( |
| MenuItemView* menu, |
| DropPosition position, |
| const ui::DropTargetEvent& event) override; |
| int GetDragOperations(MenuItemView* sender) override; |
| void WriteDragData(MenuItemView* sender, OSExchangeData* data) override; |
| void WillHideMenu(MenuItemView* menu) override; |
| bool ShouldExecuteCommandWithoutClosingMenu(int id, |
| const ui::Event& e) override; |
| bool ShouldCloseOnDragComplete() override; |
| |
| private: |
| // Performs the drop operation and updates |output_drag_op| accordingly. |
| void PerformDrop(const ui::DropTargetEvent& event, |
| ui::mojom::DragOperation& output_drag_op, |
| std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner); |
| |
| // The number of times ShowContextMenu was called. |
| int show_context_menu_count_ = 0; |
| |
| // The value of the last call to ShowContextMenu. |
| raw_ptr<MenuItemView, DanglingUntriaged> show_context_menu_source_ = nullptr; |
| |
| // ID of last executed command. |
| int execute_command_id_ = kInvalidExecuteCommandId; |
| |
| // The number of times OnMenuClosed was called. |
| int on_menu_closed_called_count_ = 0; |
| |
| // The value of the last call to OnMenuClosed. |
| raw_ptr<MenuItemView, DanglingUntriaged> on_menu_closed_menu_ = nullptr; |
| |
| // The number of times WillHideMenu was called. |
| int will_hide_menu_count_ = 0; |
| |
| // The value of the last call to WillHideMenu. |
| raw_ptr<MenuItemView, DanglingUntriaged> will_hide_menu_ = nullptr; |
| |
| bool is_drop_performed_ = false; |
| |
| bool should_execute_command_without_closing_menu_ = false; |
| |
| bool should_close_on_drag_complete_ = false; |
| |
| base::flat_set<int> commands_without_context_menus_; |
| }; |
| |
| // Test api which caches the currently active MenuController. Can be used to |
| // toggle visibility, and to clear seletion states, without performing full |
| // shutdown. This is used to simulate menus with varing states, such as during |
| // drags, without performing the entire operation. Used to test strange shutdown |
| // ordering. |
| class MenuControllerTestApi { |
| public: |
| MenuControllerTestApi(); |
| |
| MenuControllerTestApi(const MenuControllerTestApi&) = delete; |
| MenuControllerTestApi& operator=(const MenuControllerTestApi&) = delete; |
| |
| ~MenuControllerTestApi(); |
| |
| MenuController* controller() { return controller_.get(); } |
| |
| // Clears out the current and pending states, without notifying the associated |
| // menu items. |
| void ClearState(); |
| |
| // Toggles the internal showing state of |controller_| without attempting |
| // to change associated Widgets. |
| void SetShowing(bool showing); |
| |
| private: |
| base::WeakPtr<MenuController> controller_; |
| }; |
| |
| // On platforms which have menu closure animations, these functions are |
| // necessary to: |
| // 1) Disable those animations (make them take zero time) to avoid slowing |
| // down tests; |
| // 2) Wait for maybe-asynchronous menu closure to finish. |
| // On platforms without menu closure animations, these do nothing. |
| void DisableMenuClosureAnimations(); |
| void WaitForMenuClosureAnimation(); |
| |
| // An implementation of TestViewsDelegate which overrides ReleaseRef in order to |
| // call a provided callback. |
| class ReleaseRefTestViewsDelegate : public TestViewsDelegate { |
| public: |
| ReleaseRefTestViewsDelegate(); |
| ReleaseRefTestViewsDelegate(const ReleaseRefTestViewsDelegate&) = delete; |
| ReleaseRefTestViewsDelegate& operator=(const ReleaseRefTestViewsDelegate&) = |
| delete; |
| ~ReleaseRefTestViewsDelegate() override; |
| |
| void set_release_ref_callback(base::RepeatingClosure release_ref_callback) { |
| release_ref_callback_ = std::move(release_ref_callback); |
| } |
| |
| // TestViewsDelegate: |
| void ReleaseRef() override; |
| |
| private: |
| base::RepeatingClosure release_ref_callback_; |
| }; |
| |
| } // namespace test |
| } // namespace views |
| |
| #endif // UI_VIEWS_TEST_MENU_TEST_UTILS_H_ |