File: tooltip_state_manager.cc

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 (150 lines) | stat: -rw-r--r-- 5,075 bytes parent folder | download | duplicates (6)
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
// 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.

#include "ui/views/corewm/tooltip_state_manager.h"

#include <stddef.h>

#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/gfx/text_elider.h"
#include "ui/wm/public/tooltip_client.h"
#include "ui/wm/public/tooltip_observer.h"

namespace views::corewm {
namespace {

#if BUILDFLAG(IS_WIN)
// Drawing a long word in tooltip is very slow on Windows. crbug.com/513693
constexpr size_t kMaxTooltipLength = 1024;
#else
constexpr size_t kMaxTooltipLength = 2048;
#endif

}  // namespace

TooltipStateManager::TooltipStateManager(std::unique_ptr<Tooltip> tooltip)
    : tooltip_(std::move(tooltip)) {}

TooltipStateManager::~TooltipStateManager() = default;

void TooltipStateManager::AddObserver(wm::TooltipObserver* observer) {
  DCHECK(tooltip_);
  tooltip_->AddObserver(observer);
}

void TooltipStateManager::RemoveObserver(wm::TooltipObserver* observer) {
  DCHECK(tooltip_);
  tooltip_->RemoveObserver(observer);
}

int TooltipStateManager::GetMaxWidth(const gfx::Point& location) const {
  return tooltip_->GetMaxWidth(location);
}

void TooltipStateManager::HideAndReset() {
  // Hide any open tooltips.
  will_hide_tooltip_timer_.Stop();
  tooltip_->Hide();

  // Cancel pending tooltips and reset states.
  will_show_tooltip_timer_.Stop();
  tooltip_id_ = nullptr;
  tooltip_parent_window_ = nullptr;
}

void TooltipStateManager::Show(aura::Window* window,
                               const std::u16string& tooltip_text,
                               const gfx::Point& position,
                               TooltipTrigger trigger,
                               const base::TimeDelta show_delay,
                               const base::TimeDelta hide_delay) {
  HideAndReset();

  position_ = position;
  tooltip_id_ = wm::GetTooltipId(window);
  tooltip_text_ = tooltip_text;
  tooltip_parent_window_ = window;
  tooltip_trigger_ = trigger;

  std::u16string truncated_text =
      gfx::TruncateString(tooltip_text_, kMaxTooltipLength, gfx::WORD_BREAK);
  std::u16string trimmed_text;
  base::TrimWhitespace(truncated_text, base::TRIM_ALL, &trimmed_text);

  // If the string consists entirely of whitespace, then don't both showing it
  // (an empty tooltip is useless).
  if (trimmed_text.empty()) {
    return;
  }

  // Initialize the one-shot timer to show the tooltip after a delay. Any
  // running timers have already been canceled by calling HideAndReset above.
  // This ensures that the tooltip won't show up too early. The delayed
  // appearance of a tooltip is by default and the `show_delay` is only set to
  // 0 in the unit tests.
  StartWillShowTooltipTimer(trimmed_text, show_delay, hide_delay);
}

void TooltipStateManager::UpdatePositionIfNeeded(const gfx::Point& position,
                                                 TooltipTrigger trigger) {
  // The position should only be updated when the tooltip has been triggered but
  // is not yet visible. Also, we only want to allow the update when it's set
  // off by the same trigger that started the |will_show_tooltip_timer_| in
  // the first place. Otherwise, for example, the position of a keyboard
  // triggered tooltip could be updated by an unrelated mouse exited event. The
  // tooltip would then show up at the wrong location.
  if (!will_show_tooltip_timer_.IsRunning() || trigger != tooltip_trigger_) {
    return;
  }

  position_ = position;
}

void TooltipStateManager::ShowNow(const std::u16string& trimmed_text,
                                  const base::TimeDelta hide_delay) {
  if (!tooltip_parent_window_) {
    return;
  }

  if (!tooltip_parent_window_->GetRootWindow()) {
    // This can happen if the window is in the process of closing.
    return;
  }

  tooltip_->Update(tooltip_parent_window_, trimmed_text, position_,
                   tooltip_trigger_);
  tooltip_->Show();
  if (!hide_delay.is_zero()) {
    will_hide_tooltip_timer_.Start(FROM_HERE, hide_delay, this,
                                   &TooltipStateManager::HideAndReset);
  }
}

void TooltipStateManager::StartWillShowTooltipTimer(
    const std::u16string& trimmed_text,
    const base::TimeDelta show_delay,
    const base::TimeDelta hide_delay) {
  if (!show_delay.is_zero()) {
    // Start will show tooltip timer is show_delay is non-zero.
    will_show_tooltip_timer_.Start(
        FROM_HERE, show_delay,
        base::BindOnce(&TooltipStateManager::ShowNow,
                       weak_factory_.GetWeakPtr(), trimmed_text, hide_delay));
    return;
  } else {
    // This other path is needed for the unit tests to pass because Show is not
    // immediately called when we have a `show_delay` of zero.
    // TODO(bebeaudr): Fix this by ensuring that the unit tests wait for the
    // timer to fire before continuing.
    ShowNow(trimmed_text, hide_delay);
  }
}

}  // namespace views::corewm