blob: 7da7fad8d160142339471e2816331d076b116a98 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_INTERACTION_ELEMENT_TRACKER_VIEWS_H_
#define UI_VIEWS_INTERACTION_ELEMENT_TRACKER_VIEWS_H_
#include <map>
#include <memory>
#include <vector>
#include "base/scoped_multi_source_observation.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace views {
class View;
// Wraps a View in an ui::TrackedElement.
class VIEWS_EXPORT TrackedElementViews : public ui::TrackedElement {
public:
TrackedElementViews(View* view,
ui::ElementIdentifier identifier,
ui::ElementContext context);
~TrackedElementViews() override;
View* view() { return view_; }
const View* view() const { return view_; }
DECLARE_ELEMENT_TRACKER_METADATA()
private:
View* const view_;
};
// Manages TrackedElements associated with View objects.
class VIEWS_EXPORT ElementTrackerViews : private WidgetObserver {
public:
using ViewList = std::vector<View*>;
// Gets the global instance of the tracker for Views.
static ElementTrackerViews* GetInstance();
// Returns the context associated with a particular View. The context will be
// the same across all Views associated with a root Widget (such as an
// application window).
static ui::ElementContext GetContextForView(View* view);
// Returns the corresponding TrackedElementViews for the given view, or
// null if none exists. Note that views which are not visible or not added to
// a Widget may not have associated elements, and that the returned object
// may be transient.
TrackedElementViews* GetElementForView(View* view);
const TrackedElementViews* GetElementForView(const View* view) const;
// Called by View after the kUniqueElementKey property is set.
void RegisterView(ui::ElementIdentifier element_id, View* view);
// Called by View if the kUniqueElementKey property is changed from a non-null
// value.
void UnregisterView(ui::ElementIdentifier element_id, View* view);
// Called by a View when the user activates it (clicks a button, selects a
// menu item, etc.)
void NotifyViewActivated(ui::ElementIdentifier element_id, View* view);
private:
friend class base::NoDestructor<ElementTrackerViews>;
class ElementDataViews;
ElementTrackerViews();
~ElementTrackerViews() override;
// WidgetObserver:
void OnWidgetVisibilityChanged(Widget* widget, bool visible) override;
void OnWidgetDestroying(Widget* widget) override;
// We do not get notified at the View level if a view's widget has not yet
// been shown. We need this notification to know when the view is actually
// visible to the user. So if a view is added to the trakcer or is added to
// a widget, and its widget is not visible, we watch it until it is (or it is
// destroyed).
void MaybeObserveWidget(Widget* widget);
std::map<ui::ElementIdentifier, std::unique_ptr<ElementDataViews>>
element_data_;
base::ScopedMultiSourceObservation<Widget, WidgetObserver> widget_observer_{
this};
};
} // namespace views
#endif // UI_VIEWS_INTERACTION_ELEMENT_TRACKER_VIEWS_H_