File: popover_data.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (175 lines) | stat: -rw-r--r-- 6,456 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_POPOVER_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_POPOVER_DATA_H_

#include "base/check_op.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_rare_data_field.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/html/closewatcher/close_watcher.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html_element_type_helpers.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"

namespace blink {

enum class PopoverVisibilityState {
  kHidden,
  kShowing,
};

using PopoverHoverShowMap =
    HeapHashMap<WeakMember<const HTMLFormControlElement>, TaskHandle>;

class PopoverData final : public GarbageCollected<PopoverData>,
                          public ElementRareDataField {
 public:
  PopoverData() = default;
  PopoverData(const PopoverData&) = delete;
  PopoverData& operator=(const PopoverData&) = delete;

  PopoverVisibilityState visibilityState() const { return visibility_state_; }
  void setVisibilityState(PopoverVisibilityState visibility_state) {
    visibility_state_ = visibility_state;
  }

  PopoverValueType type() const { return type_; }
  void setType(PopoverValueType type) {
    type_ = type;
    DCHECK_NE(type, PopoverValueType::kNone)
        << "Remove PopoverData rather than setting kNone type";
  }

  Element* invoker() const { return invoker_.Get(); }
  void setInvoker(Element* element) { invoker_ = element; }

  Element* previouslyFocusedElement() const {
    return previously_focused_element_.Get();
  }
  void setPreviouslyFocusedElement(Element* element) {
    previously_focused_element_ = element;
  }

  bool hasPendingToggleEventTask() const {
    return pending_toggle_event_task_.IsActive();
  }
  void cancelPendingToggleEventTask() { pending_toggle_event_task_.Cancel(); }
  void setPendingToggleEventTask(TaskHandle&& task) {
    DCHECK(!pending_toggle_event_task_.IsActive());
    pending_toggle_event_task_ = std::move(task);
  }

  bool pendingToggleEventStartedClosed() const {
    DCHECK(hasPendingToggleEventTask());
    return pending_toggle_event_started_closed_;
  }
  void setPendingToggleEventStartedClosed(bool was_closed) {
    DCHECK(!hasPendingToggleEventTask());
    pending_toggle_event_started_closed_ = was_closed;
  }

  class ScopedStartShowingOrHiding {
    STACK_ALLOCATED();

   public:
    explicit ScopedStartShowingOrHiding(const Element& popover,
                                        bool show_warning = true)
        : popover_(popover),
          was_set_(popover.GetPopoverData()->hiding_or_showing_this_popover_) {
      if (was_set_ && show_warning) {
        if (RuntimeEnabledFeatures::HTMLInterestTargetAttributeEnabled(
                popover.GetDocument().GetExecutionContext())) {
          popover_.GetDocument().AddConsoleMessage(
              MakeGarbageCollected<ConsoleMessage>(
                  mojom::blink::ConsoleMessageSource::kOther,
                  mojom::blink::ConsoleMessageLevel::kWarning,
                  "The `beforetoggle` event handler for a popover triggered "
                  "another popover to be shown or hidden. Or a `loseinterest` "
                  "event handler was cancelled. This is not recommended."));
        } else {
          popover_.GetDocument().AddConsoleMessage(
              MakeGarbageCollected<ConsoleMessage>(
                  mojom::blink::ConsoleMessageSource::kOther,
                  mojom::blink::ConsoleMessageLevel::kWarning,
                  "The `beforetoggle` event handler for a popover triggered "
                  "another popover to be shown or hidden. This is not "
                  "recommended."));
        }
      } else {
        popover_.GetPopoverData()->hiding_or_showing_this_popover_ = true;
      }
    }
    ~ScopedStartShowingOrHiding() {
      if (!was_set_ && popover_.GetPopoverData()) {
        popover_.GetPopoverData()->hiding_or_showing_this_popover_ = false;
      }
    }
    explicit operator bool() const { return was_set_; }

   private:
    const Element& popover_;
    bool was_set_;
  };

  PopoverHoverShowMap& hoverShowTasks() { return hover_show_tasks_; }

  void setHoverHideTask(TaskHandle&& task) {
    if (hover_hide_task_.IsActive()) {
      hover_hide_task_.Cancel();
    }
    hover_hide_task_ = std::move(task);
  }

  Element* implicitAnchor() const { return implicit_anchor_.Get(); }
  void setImplicitAnchor(Element* element) { implicit_anchor_ = element; }

  CloseWatcher* closeWatcher() { return close_watcher_.Get(); }
  void setCloseWatcher(CloseWatcher* close_watcher) {
    close_watcher_ = close_watcher;
  }

  void Trace(Visitor* visitor) const override {
    visitor->Trace(invoker_);
    visitor->Trace(previously_focused_element_);
    visitor->Trace(hover_show_tasks_);
    visitor->Trace(implicit_anchor_);
    visitor->Trace(close_watcher_);
    ElementRareDataField::Trace(visitor);
  }

 private:
  PopoverVisibilityState visibility_state_ = PopoverVisibilityState::kHidden;
  PopoverValueType type_ = PopoverValueType::kNone;
  WeakMember<Element> invoker_;
  WeakMember<Element> previously_focused_element_;

  // Any pending 'toggle' event waiting to be fired. Used for coalescing
  // behavior so that only one such event is fired.
  TaskHandle pending_toggle_event_task_;
  bool pending_toggle_event_started_closed_;

  // True when we're in the middle of trying to hide/show this popover.
  bool hiding_or_showing_this_popover_;

  // Map from elements with the 'popovertarget' attribute and
  // `popovertargetaction=hover` to a task that will show the popover after a
  // delay.
  PopoverHoverShowMap hover_show_tasks_;
  // A task that hides the popover after a delay.
  TaskHandle hover_hide_task_;

  // Used to set up an anchor relationship separately from CSS `anchor`
  // references.
  WeakMember<Element> implicit_anchor_;

  Member<CloseWatcher> close_watcher_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_POPOVER_DATA_H_