| // Copyright 2024 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_CONTROLS_MENU_MENU_RUNNER_IMPL_REMOTE_COCOA_H_ |
| #define UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_REMOTE_COCOA_H_ |
| |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "base/unguessable_token.h" |
| #include "components/remote_cocoa/common/menu.mojom.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "mojo/public/cpp/bindings/receiver_set.h" |
| #include "ui/views/controls/menu/menu_runner_impl_interface.h" |
| |
| namespace views { |
| |
| // Menu runner implementation that serializes the menu model over mojo, to then |
| // use NSMenu in possibly a different process to show a context menu. |
| // Like MenuRunnerImplCocoa this only supports context menus. |
| class VIEWS_EXPORT MenuRunnerImplRemoteCocoa |
| : public internal::MenuRunnerImplInterface, |
| public remote_cocoa::mojom::MenuHost { |
| public: |
| MenuRunnerImplRemoteCocoa(ui::MenuModel* menu_model, |
| base::RepeatingClosure on_menu_closed_callback); |
| |
| MenuRunnerImplRemoteCocoa(const MenuRunnerImplRemoteCocoa&) = delete; |
| MenuRunnerImplRemoteCocoa& operator=(const MenuRunnerImplRemoteCocoa&) = |
| delete; |
| |
| // Runs the menu at the specific `anchor` in screen coordinates. If specified, |
| // `target_view_id` is used to look up the NSView to use as target of the |
| // menu (which is then used by AppKit to for example populate the Services |
| // submenu). |
| void RunMenu(Widget* widget, |
| const gfx::Point& anchor, |
| uint64_t target_view_id = 0); |
| |
| // Updates the label and state of the top-level menu item with id equal to |
| // `command_id`. Should only be called while the menu is running. |
| void UpdateMenuItem(int command_id, |
| bool enabled, |
| bool hidden, |
| const std::u16string& title); |
| |
| // MenuRunnerImplInterface: |
| bool IsRunning() const override; |
| void Release() override; |
| void RunMenuAt( |
| Widget* parent, |
| MenuButtonController* button_controller, |
| const gfx::Rect& bounds, |
| MenuAnchorPosition anchor, |
| ui::mojom::MenuSourceType source_type, |
| int32_t run_types, |
| gfx::NativeView native_view_for_gestures, |
| std::optional<gfx::RoundedCornersF> corners, |
| std::optional<std::string> show_menu_host_duration_histogram) override; |
| void Cancel() override; |
| base::TimeTicks GetClosingEventTime() const override; |
| |
| private: |
| ~MenuRunnerImplRemoteCocoa() override; |
| |
| // remote_cocoa::mojom::MenuHost: |
| void CommandActivated(int32_t command_id, int32_t event_flags) override; |
| void MenuClosed() override; |
| |
| // Recursively converts `menu_model` to mojom structs. Since we rely on |
| // command IDs being unique, this uses `command_ids` to verify that all |
| // menu items in the model do in fact have unique command IDs. |
| std::vector<remote_cocoa::mojom::MenuItemPtr> ModelToMojo( |
| const ui::MenuModel& menu_model, |
| std::set<int>& command_ids); |
| |
| raw_ptr<ui::MenuModel> menu_model_; |
| mojo::Receiver<remote_cocoa::mojom::MenuHost> host_receiver_{this}; |
| mojo::Remote<remote_cocoa::mojom::Menu> menu_remote_; |
| |
| // Is the context menu currently being displayed? |
| bool running_ = false; |
| |
| // The timestamp of the event which closed the menu - or 0. |
| base::TimeTicks closing_event_time_; |
| |
| base::RepeatingClosure on_menu_closed_callback_; |
| }; |
| |
| } // namespace views |
| |
| #endif // UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_REMOTE_COCOA_H_ |