// 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 UI_BASE_INTERACTION_ELEMENT_TRACKER_MAC_H_
#define UI_BASE_INTERACTION_ELEMENT_TRACKER_MAC_H_
#import <Cocoa/Cocoa.h>
#include <map>
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/no_destructor.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/base/interaction/framework_specific_implementation.h"
#include "ui/gfx/geometry/rect.h"
namespace ui {
// Tracked element representing a native Mac visual element (typically a menu or
// menu item, since we use Views for everything else).
class COMPONENT_EXPORT(UI_BASE) TrackedElementMac : public TrackedElement {
public:
TrackedElementMac(ElementIdentifier identifier,
ElementContext context,
const gfx::Rect& screen_bounds);
~TrackedElementMac() override;
// TrackedElement:
gfx::Rect GetScreenBounds() const override;
DECLARE_FRAMEWORK_SPECIFIC_METADATA()
private:
const gfx::Rect screen_bounds_;
};
// Helper class for translating between Mac visual elements and TrackedElements.
// Largely used to track native menus and menu items, as almost all other
// surfaces are rendered using Views.
class COMPONENT_EXPORT(UI_BASE) ElementTrackerMac {
public:
ElementTrackerMac(const ElementTrackerMac& other) = delete;
void operator=(const ElementTrackerMac& other) = delete;
// Gets the global instance of the tracker for native Mac elements.
static ElementTrackerMac* GetInstance();
// Called before a root menu will be displayed.
void NotifyMenuWillShow(NSMenu* menu, ElementContext context);
// Called after a root menu fully fades out.
void NotifyMenuDoneShowing(NSMenu* menu);
// Called when a specific menu item becomes visible.
void NotifyMenuItemShown(NSMenu* menu,
ElementIdentifier identifier,
const gfx::Rect& screen_bounds);
// Called when a specific menu item is hidden.
void NotifyMenuItemHidden(NSMenu* menu, ElementIdentifier identifier);
// Called when the user clicks on a menu item. This callback will happen after
// all of the Hidden() calls happen, but before NotifyMenuDoneShowing() is
// called.
void NotifyMenuItemActivated(NSMenu* menu, ElementIdentifier identifier);
// Returns the root menu for a given context, if any.
NSMenu* GetRootMenuForContext(ElementContext context);
protected:
ElementTrackerMac();
virtual ~ElementTrackerMac();
// Returns the root menu for a given `menu` (which might be the same menu if
// it is the root). Override for tests if you want to use fake NSMenu objects.
virtual NSMenu* GetRootMenu(NSMenu* menu) const;
// Used in testing to determine if all data has been properly cleared out.
bool is_tracking_any_menus() const { return !root_menu_to_data_.empty(); }
private:
friend class base::NoDestructor<ElementTrackerMac>;
class MenuData;
std::map<NSMenu*, MenuData> root_menu_to_data_;
};
} // namespace ui
#endif // UI_BASE_INTERACTION_ELEMENT_TRACKER_MAC_H_