blob: 1665f1a5afdf33ff527ae92a4af3afd419e2b42b [file] [log] [blame]
[email protected]5139f1e2012-01-18 23:58:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]a7eb0182011-12-21 12:33:312// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]e73bd7802012-02-17 20:10:345#include "ash/shell.h"
[email protected]1dd1c1b2012-02-17 22:04:476#include "ash/test/ash_test_base.h"
[email protected]2f744282011-12-23 22:40:527#include "ash/tooltips/tooltip_controller.h"
[email protected]a7eb0182011-12-21 12:33:318#include "base/utf_string_conversions.h"
9#include "ui/aura/client/tooltip_client.h"
[email protected]1aad3322012-06-06 06:37:0910#include "ui/aura/cursor_manager.h"
11#include "ui/aura/env.h"
[email protected]a7eb0182011-12-21 12:33:3112#include "ui/aura/root_window.h"
[email protected]68a8e062012-01-26 01:39:4913#include "ui/aura/test/event_generator.h"
[email protected]a7eb0182011-12-21 12:33:3114#include "ui/aura/window.h"
[email protected]1eea6142012-03-22 09:30:0115#include "ui/base/resource/resource_bundle.h"
16#include "ui/base/text/text_elider.h"
17#include "ui/gfx/font.h"
[email protected]a7eb0182011-12-21 12:33:3118#include "ui/gfx/point.h"
19#include "ui/views/view.h"
20#include "ui/views/widget/widget.h"
21
[email protected]55f593352011-12-24 05:42:4622namespace ash {
[email protected]a7eb0182011-12-21 12:33:3123namespace test {
24
25namespace {
26
27class TooltipTestView : public views::View {
28 public:
29 TooltipTestView() : views::View() {
30 }
31
32 void set_tooltip_text(string16 tooltip_text) { tooltip_text_ = tooltip_text; }
33
34 // Overridden from views::View
35 bool GetTooltipText(const gfx::Point& p, string16* tooltip) const {
36 *tooltip = tooltip_text_;
37 return true;
38 }
39
40 private:
41 string16 tooltip_text_;
42
43 DISALLOW_COPY_AND_ASSIGN(TooltipTestView);
44};
45
46views::Widget* CreateNewWidget() {
47 views::Widget* widget = new views::Widget;
48 views::Widget::InitParams params;
49 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
50 params.accept_events = true;
51 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
[email protected]42713f72012-05-25 00:41:5052 params.parent = Shell::GetPrimaryRootWindow();
[email protected]a7eb0182011-12-21 12:33:3153 params.child = true;
54 widget->Init(params);
55 widget->Show();
56 return widget;
57}
58
59void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
60 if (!widget->GetContentsView()) {
61 views::View* contents_view = new views::View;
62 widget->SetContentsView(contents_view);
63 }
64
65 views::View* contents_view = widget->GetContentsView();
66 contents_view->AddChildView(view);
67 view->SetBounds(contents_view->width(), 0, 100, 100);
68 gfx::Rect contents_view_bounds = contents_view->bounds();
69 contents_view_bounds = contents_view_bounds.Union(view->bounds());
70 contents_view->SetBoundsRect(contents_view_bounds);
71 widget->SetBounds(contents_view_bounds);
72}
73
[email protected]55f593352011-12-24 05:42:4674ash::internal::TooltipController* GetController() {
75 return static_cast<ash::internal::TooltipController*>(
[email protected]42713f72012-05-25 00:41:5076 aura::client::GetTooltipClient(Shell::GetPrimaryRootWindow()));
[email protected]a7eb0182011-12-21 12:33:3177}
78
[email protected]1eea6142012-03-22 09:30:0179gfx::Font GetDefaultFont() {
80 return ui::ResourceBundle::GetSharedInstance().GetFont(
81 ui::ResourceBundle::BaseFont);
82}
83
[email protected]a7eb0182011-12-21 12:33:3184} // namespace
85
[email protected]1dd1c1b2012-02-17 22:04:4786class TooltipControllerTest : public AshTestBase {
[email protected]a7eb0182011-12-21 12:33:3187 public:
88 TooltipControllerTest() {}
89 virtual ~TooltipControllerTest() {}
90
91 string16 GetTooltipText() {
92 return GetController()->tooltip_text_;
93 }
94
95 aura::Window* GetTooltipWindow() {
96 return GetController()->tooltip_window_;
97 }
98
99 void FireTooltipTimer() {
100 GetController()->TooltipTimerFired();
101 }
102
[email protected]5139f1e2012-01-18 23:58:02103 bool IsTooltipVisible() {
104 return GetController()->IsTooltipVisible();
105 }
106
[email protected]1eea6142012-03-22 09:30:01107 void TrimTooltipToFit(string16* text,
108 int* max_width,
109 int* line_count,
110 int x,
111 int y) {
112 ash::internal::TooltipController::TrimTooltipToFit(text, max_width,
113 line_count, x, y);
114 }
115
[email protected]a7eb0182011-12-21 12:33:31116 private:
117 DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest);
118};
119
120TEST_F(TooltipControllerTest, NonNullTooltipClient) {
[email protected]42713f72012-05-25 00:41:50121 EXPECT_TRUE(aura::client::GetTooltipClient(Shell::GetPrimaryRootWindow())
122 != NULL);
[email protected]dc03f982012-05-04 21:12:49123 EXPECT_EQ(string16(), GetTooltipText());
[email protected]a7eb0182011-12-21 12:33:31124 EXPECT_EQ(NULL, GetTooltipWindow());
[email protected]5139f1e2012-01-18 23:58:02125 EXPECT_FALSE(IsTooltipVisible());
[email protected]a7eb0182011-12-21 12:33:31126}
127
128TEST_F(TooltipControllerTest, ViewTooltip) {
[email protected]4c616542012-02-07 23:37:10129 scoped_ptr<views::Widget> widget(CreateNewWidget());
[email protected]a7eb0182011-12-21 12:33:31130 TooltipTestView* view = new TooltipTestView;
[email protected]4c616542012-02-07 23:37:10131 AddViewToWidgetAndResize(widget.get(), view);
[email protected]a7eb0182011-12-21 12:33:31132 view->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
[email protected]dc03f982012-05-04 21:12:49133 EXPECT_EQ(string16(), GetTooltipText());
[email protected]a7eb0182011-12-21 12:33:31134 EXPECT_EQ(NULL, GetTooltipWindow());
[email protected]42713f72012-05-25 00:41:50135 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
[email protected]68a8e062012-01-26 01:39:49136 generator.MoveMouseToCenterOf(widget->GetNativeView());
[email protected]a7eb0182011-12-21 12:33:31137
[email protected]a7eb0182011-12-21 12:33:31138 aura::Window* window = widget->GetNativeView();
[email protected]42713f72012-05-25 00:41:50139 EXPECT_EQ(window, Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
[email protected]68a8e062012-01-26 01:39:49140 generator.current_location()));
[email protected]a7eb0182011-12-21 12:33:31141 string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
[email protected]6e9f6aa2012-02-09 04:16:20142 EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
[email protected]dc03f982012-05-04 21:12:49143 EXPECT_EQ(string16(), GetTooltipText());
[email protected]a7eb0182011-12-21 12:33:31144 EXPECT_EQ(window, GetTooltipWindow());
145
146 // Fire tooltip timer so tooltip becomes visible.
147 FireTooltipTimer();
148
[email protected]5139f1e2012-01-18 23:58:02149 EXPECT_TRUE(IsTooltipVisible());
[email protected]68a8e062012-01-26 01:39:49150 generator.MoveMouseBy(1, 0);
[email protected]a7eb0182011-12-21 12:33:31151
[email protected]5139f1e2012-01-18 23:58:02152 EXPECT_TRUE(IsTooltipVisible());
[email protected]6e9f6aa2012-02-09 04:16:20153 EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
[email protected]a7eb0182011-12-21 12:33:31154 EXPECT_EQ(expected_tooltip, GetTooltipText());
155 EXPECT_EQ(window, GetTooltipWindow());
156}
157
158TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
[email protected]4c616542012-02-07 23:37:10159 scoped_ptr<views::Widget> widget(CreateNewWidget());
[email protected]a7eb0182011-12-21 12:33:31160 TooltipTestView* view1 = new TooltipTestView;
[email protected]4c616542012-02-07 23:37:10161 AddViewToWidgetAndResize(widget.get(), view1);
[email protected]a7eb0182011-12-21 12:33:31162 view1->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
[email protected]dc03f982012-05-04 21:12:49163 EXPECT_EQ(string16(), GetTooltipText());
[email protected]a7eb0182011-12-21 12:33:31164 EXPECT_EQ(NULL, GetTooltipWindow());
165
166 TooltipTestView* view2 = new TooltipTestView;
[email protected]4c616542012-02-07 23:37:10167 AddViewToWidgetAndResize(widget.get(), view2);
[email protected]a7eb0182011-12-21 12:33:31168
169 aura::Window* window = widget->GetNativeView();
[email protected]a7eb0182011-12-21 12:33:31170
171 // Fire tooltip timer so tooltip becomes visible.
[email protected]42713f72012-05-25 00:41:50172 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
[email protected]68a8e062012-01-26 01:39:49173 generator.MoveMouseRelativeTo(window,
174 view1->bounds().CenterPoint());
[email protected]a7eb0182011-12-21 12:33:31175 FireTooltipTimer();
[email protected]5139f1e2012-01-18 23:58:02176 EXPECT_TRUE(IsTooltipVisible());
[email protected]a7eb0182011-12-21 12:33:31177 for (int i = 0; i < 50; i++) {
[email protected]68a8e062012-01-26 01:39:49178 generator.MoveMouseBy(1, 0);
[email protected]5139f1e2012-01-18 23:58:02179 EXPECT_TRUE(IsTooltipVisible());
[email protected]a7eb0182011-12-21 12:33:31180 EXPECT_EQ(window,
[email protected]42713f72012-05-25 00:41:50181 Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
[email protected]68a8e062012-01-26 01:39:49182 generator.current_location()));
[email protected]a7eb0182011-12-21 12:33:31183 string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
[email protected]6e9f6aa2012-02-09 04:16:20184 EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
[email protected]a7eb0182011-12-21 12:33:31185 EXPECT_EQ(expected_tooltip, GetTooltipText());
186 EXPECT_EQ(window, GetTooltipWindow());
187 }
188 for (int i = 0; i < 50; i++) {
[email protected]68a8e062012-01-26 01:39:49189 generator.MoveMouseBy(1, 0);
[email protected]5139f1e2012-01-18 23:58:02190 EXPECT_FALSE(IsTooltipVisible());
[email protected]a7eb0182011-12-21 12:33:31191 EXPECT_EQ(window,
[email protected]42713f72012-05-25 00:41:50192 Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
[email protected]68a8e062012-01-26 01:39:49193 generator.current_location()));
[email protected]6e9f6aa2012-02-09 04:16:20194 string16 expected_tooltip; // = ""
195 EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
[email protected]a7eb0182011-12-21 12:33:31196 EXPECT_EQ(expected_tooltip, GetTooltipText());
197 EXPECT_EQ(window, GetTooltipWindow());
198 }
199}
200
[email protected]5139f1e2012-01-18 23:58:02201TEST_F(TooltipControllerTest, EnableOrDisableTooltips) {
[email protected]4c616542012-02-07 23:37:10202 scoped_ptr<views::Widget> widget(CreateNewWidget());
[email protected]5139f1e2012-01-18 23:58:02203 TooltipTestView* view = new TooltipTestView;
[email protected]4c616542012-02-07 23:37:10204 AddViewToWidgetAndResize(widget.get(), view);
[email protected]5139f1e2012-01-18 23:58:02205 view->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
[email protected]dc03f982012-05-04 21:12:49206 EXPECT_EQ(string16(), GetTooltipText());
[email protected]5139f1e2012-01-18 23:58:02207 EXPECT_EQ(NULL, GetTooltipWindow());
208
[email protected]42713f72012-05-25 00:41:50209 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
[email protected]68a8e062012-01-26 01:39:49210 generator.MoveMouseRelativeTo(widget->GetNativeView(),
211 view->bounds().CenterPoint());
[email protected]5139f1e2012-01-18 23:58:02212 string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
213
214 // Fire tooltip timer so tooltip becomes visible.
215 FireTooltipTimer();
216 EXPECT_TRUE(IsTooltipVisible());
217
218 // Diable tooltips and check again.
219 GetController()->SetTooltipsEnabled(false);
220 EXPECT_FALSE(IsTooltipVisible());
221 FireTooltipTimer();
222 EXPECT_FALSE(IsTooltipVisible());
223
224 // Enable tooltips back and check again.
225 GetController()->SetTooltipsEnabled(true);
226 EXPECT_FALSE(IsTooltipVisible());
227 FireTooltipTimer();
228 EXPECT_TRUE(IsTooltipVisible());
229}
230
[email protected]3341c652012-04-24 02:02:28231TEST_F(TooltipControllerTest, HideTooltipWhenCursorHidden) {
232 scoped_ptr<views::Widget> widget(CreateNewWidget());
233 TooltipTestView* view = new TooltipTestView;
234 AddViewToWidgetAndResize(widget.get(), view);
235 view->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
[email protected]dc03f982012-05-04 21:12:49236 EXPECT_EQ(string16(), GetTooltipText());
[email protected]3341c652012-04-24 02:02:28237 EXPECT_EQ(NULL, GetTooltipWindow());
238
[email protected]42713f72012-05-25 00:41:50239 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
[email protected]3341c652012-04-24 02:02:28240 generator.MoveMouseRelativeTo(widget->GetNativeView(),
241 view->bounds().CenterPoint());
242 string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
243
244 // Fire tooltip timer so tooltip becomes visible.
245 FireTooltipTimer();
246 EXPECT_TRUE(IsTooltipVisible());
247
248 // Hide the cursor and check again.
[email protected]1aad3322012-06-06 06:37:09249 aura::Env::GetInstance()->cursor_manager()->ShowCursor(false);
[email protected]3341c652012-04-24 02:02:28250 FireTooltipTimer();
251 EXPECT_FALSE(IsTooltipVisible());
252
253 // Show the cursor and re-check.
[email protected]1aad3322012-06-06 06:37:09254 aura::Env::GetInstance()->cursor_manager()->ShowCursor(true);
[email protected]3341c652012-04-24 02:02:28255 FireTooltipTimer();
256 EXPECT_TRUE(IsTooltipVisible());
257}
258
[email protected]1eea6142012-03-22 09:30:01259TEST_F(TooltipControllerTest, TrimTooltipToFitTests) {
260 string16 tooltip;
261 int max_width, line_count, expect_lines;
262 int max_pixel_width = 400; // copied from constants in tooltip_controller.cc
263 int max_lines = 10; // copied from constants in tooltip_controller.cc
264 gfx::Font font = GetDefaultFont();
265 size_t tooltip_len;
266
267 // Error in computed size vs. expected size should not be greater than the
268 // size of the longest word.
269 int error_in_pixel_width = font.GetStringWidth(ASCIIToUTF16("tooltip"));
270
271 // Long tooltips should wrap to next line
272 tooltip.clear();
273 max_width = line_count = -1;
274 expect_lines = 3;
275 for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
276 tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
277 tooltip_len = tooltip.length();
278 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
279 EXPECT_NEAR(max_pixel_width, max_width, error_in_pixel_width);
280 EXPECT_EQ(expect_lines, line_count);
281 EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length());
282
283 // More than |max_lines| lines should get truncated at 10 lines.
284 tooltip.clear();
285 max_width = line_count = -1;
286 expect_lines = 13;
287 for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
288 tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
289 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
290 EXPECT_NEAR(max_pixel_width, max_width, error_in_pixel_width);
291 EXPECT_EQ(max_lines, line_count);
292
293 // Long multi line tooltips should wrap individual lines.
294 tooltip.clear();
295 max_width = line_count = -1;
296 expect_lines = 4;
297 for (; font.GetStringWidth(tooltip) <= (expect_lines - 2) * max_pixel_width;)
298 tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
299 tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n"));
300 tooltip_len = tooltip.length();
301 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
302 EXPECT_NEAR(max_pixel_width, max_width, error_in_pixel_width);
303 EXPECT_EQ(expect_lines, line_count);
304 // We may have inserted the line break above near a space which will get
305 // trimmed. Hence we may be off by 1 in the final tooltip length calculation.
306 EXPECT_NEAR(tooltip_len + expect_lines - 2, tooltip.length(), 1);
307
[email protected]6c114e42012-03-22 10:02:38308#if !defined(OS_WIN)
[email protected]1eea6142012-03-22 09:30:01309 // Tooltip with really long word gets elided.
310 tooltip.clear();
311 max_width = line_count = -1;
312 tooltip = UTF8ToUTF16(std::string('a', max_pixel_width));
313 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
314 EXPECT_NEAR(max_pixel_width, max_width, 5);
315 EXPECT_EQ(1, line_count);
316 EXPECT_EQ(ui::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font,
317 max_pixel_width, ui::ELIDE_AT_END), tooltip);
[email protected]6c114e42012-03-22 10:02:38318#endif
[email protected]1eea6142012-03-22 09:30:01319
320 // Normal small tooltip should stay as is.
321 tooltip.clear();
322 max_width = line_count = -1;
323 tooltip = ASCIIToUTF16("Small Tooltip");
324 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
325 EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tooltip")), max_width);
326 EXPECT_EQ(1, line_count);
327 EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip);
328
329 // Normal small multi-line tooltip should stay as is.
330 tooltip.clear();
331 max_width = line_count = -1;
332 tooltip = ASCIIToUTF16("Multi line\nTooltip");
333 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
334 int expected_width = font.GetStringWidth(ASCIIToUTF16("Multi line"));
335 expected_width = std::max(expected_width,
336 font.GetStringWidth(ASCIIToUTF16("Tooltip")));
337 EXPECT_EQ(expected_width, max_width);
338 EXPECT_EQ(2, line_count);
339 EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip);
340
341 // Whitespaces in tooltips are preserved.
342 tooltip.clear();
343 max_width = line_count = -1;
344 tooltip = ASCIIToUTF16("Small Tool t\tip");
345 TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
346 EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tool t\tip")), max_width);
347 EXPECT_EQ(1, line_count);
348 EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip);
349}
350
[email protected]a7eb0182011-12-21 12:33:31351} // namespace test
[email protected]55f593352011-12-24 05:42:46352} // namespace ash