summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-23 19:08:04 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-23 19:08:04 +0000
commita1b7a82fbb37bce916ef205bf862cb940b5307df (patch)
tree91be529daf93c6b1d3186876b042ac3e2adcfa58
parent4447016b31992cea934c3f83fb5d0ddd4147f56e (diff)
downloadchromium_src-a1b7a82fbb37bce916ef205bf862cb940b5307df.zip
chromium_src-a1b7a82fbb37bce916ef205bf862cb940b5307df.tar.gz
chromium_src-a1b7a82fbb37bce916ef205bf862cb940b5307df.tar.bz2
Gets tooltips to work for desktop aura. This constrains the tooltips
to the bounds of the Widget. We'll see how well that works. BUG=175441 TEST=make sure tooltips work for win-aura. R=varunjain@chromium.org Review URL: https://chromiumcodereview.appspot.com/12334017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184324 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/ash.gyp2
-rw-r--r--ash/ash_switches.cc3
-rw-r--r--ash/ash_switches.h1
-rw-r--r--ash/shell.cc8
-rw-r--r--ash/shell.h6
-rw-r--r--ash/shell/lock_view.cc3
-rw-r--r--ash/tooltips/tooltip_controller_unittest.cc413
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc2
-rw-r--r--chrome/browser/ui/views/chrome_views_delegate.cc2
-rw-r--r--ui/views/corewm/corewm_switches.cc2
-rw-r--r--ui/views/corewm/corewm_switches.h1
-rw-r--r--ui/views/corewm/tooltip_controller.cc (renamed from ash/tooltips/tooltip_controller.cc)180
-rw-r--r--ui/views/corewm/tooltip_controller.h (renamed from ash/tooltips/tooltip_controller.h)64
-rw-r--r--ui/views/corewm/tooltip_controller_test_helper.cc73
-rw-r--r--ui/views/corewm/tooltip_controller_test_helper.h75
-rw-r--r--ui/views/corewm/tooltip_controller_unittest.cc414
-rw-r--r--ui/views/views.gyp9
-rw-r--r--ui/views/widget/desktop_aura/desktop_native_widget_aura.cc19
-rw-r--r--ui/views/widget/desktop_aura/desktop_native_widget_aura.h5
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_win.cc1
-rw-r--r--ui/views/widget/desktop_aura/desktop_screen_position_client.cc3
-rw-r--r--ui/views/widget/native_widget_aura.cc3
-rw-r--r--ui/views/widget/tooltip_manager_aura.cc32
-rw-r--r--ui/views/widget/tooltip_manager_aura.h12
24 files changed, 813 insertions, 520 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index e7f1b7e..6336f08 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -291,8 +291,6 @@
'system/user/user_observer.h',
'system/web_notification/web_notification_tray.cc',
'system/web_notification/web_notification_tray.h',
- 'tooltips/tooltip_controller.cc',
- 'tooltips/tooltip_controller.h',
'touch/touch_observer_hud.cc',
'touch/touch_observer_hud.h',
'touch/touch_uma.cc',
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc
index 13636d8..bc0877d 100644
--- a/ash/ash_switches.cc
+++ b/ash/ash_switches.cc
@@ -108,9 +108,6 @@ const char kAshTouchHud[] = "ash-touch-hud";
// instead of displaying an interactive animation.
const char kAuraLegacyPowerButton[] = "aura-legacy-power-button";
-// Avoid drawing drop shadows under windows.
-const char kAuraNoShadows[] = "aura-no-shadows";
-
// Overrides all displays' orientation. The value should be one of 0
// (normal), 1 (90 degrees clockwise), 2 (180 degrees) or 3 (270
// degrees clockwise).
diff --git a/ash/ash_switches.h b/ash/ash_switches.h
index 233bfbd..0a65d77 100644
--- a/ash/ash_switches.h
+++ b/ash/ash_switches.h
@@ -44,7 +44,6 @@ ASH_EXPORT extern const char kAshImmersiveHideTabIndicators[];
ASH_EXPORT extern const char kAshSecondaryDisplayLayout[];
ASH_EXPORT extern const char kAshTouchHud[];
ASH_EXPORT extern const char kAuraLegacyPowerButton[];
-ASH_EXPORT extern const char kAuraNoShadows[];
ASH_EXPORT extern const char kAshOverrideDisplayOrientation[];
} // namespace switches
diff --git a/ash/shell.cc b/ash/shell.cc
index 1a386ea..e44c477 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -34,7 +34,6 @@
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
-#include "ash/tooltips/tooltip_controller.h"
#include "ash/touch/touch_observer_hud.h"
#include "ash/wm/activation_controller.h"
#include "ash/wm/always_on_top_controller.h"
@@ -89,6 +88,7 @@
#include "ui/views/corewm/focus_controller.h"
#include "ui/views/corewm/input_method_event_filter.h"
#include "ui/views/corewm/shadow_controller.h"
+#include "ui/views/corewm/tooltip_controller.h"
#include "ui/views/corewm/visibility_controller.h"
#include "ui/views/corewm/window_modality_controller.h"
#include "ui/views/focus/focus_manager_factory.h"
@@ -536,8 +536,8 @@ void Shell::Init() {
video_detector_.reset(new VideoDetector);
window_cycle_controller_.reset(new WindowCycleController(activation_client_));
- tooltip_controller_.reset(new internal::TooltipController(
- drag_drop_controller_.get()));
+ tooltip_controller_.reset(new views::corewm::TooltipController(
+ gfx::SCREEN_TYPE_ALTERNATE));
AddPreTargetHandler(tooltip_controller_.get());
event_client_.reset(new internal::EventClientImpl);
@@ -553,7 +553,7 @@ void Shell::Init() {
// StatusAreaWidget uses Shell's CapsLockDelegate.
caps_lock_delegate_.reset(delegate_->CreateCapsLockDelegate());
- if (!command_line->HasSwitch(switches::kAuraNoShadows)) {
+ if (!command_line->HasSwitch(views::corewm::switches::kNoDropShadows)) {
resize_shadow_controller_.reset(new internal::ResizeShadowController());
shadow_controller_.reset(
new views::corewm::ShadowController(GetPrimaryRootWindow()));
diff --git a/ash/shell.h b/ash/shell.h
index d57f519..168854f 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -58,6 +58,7 @@ namespace corewm {
class CompoundEventFilter;
class InputMethodEventFilter;
class ShadowController;
+class TooltipController;
class VisibilityController;
class WindowModalityController;
}
@@ -118,7 +119,6 @@ class SlowAnimationEventFilter;
class StatusAreaWidget;
class SystemGestureEventFilter;
class SystemModalContainerEventFilter;
-class TooltipController;
class TouchObserverHUD;
class WorkspaceController;
}
@@ -285,7 +285,7 @@ class ASH_EXPORT Shell
views::corewm::CompoundEventFilter* env_filter() {
return env_filter_.get();
}
- internal::TooltipController* tooltip_controller() {
+ views::corewm::TooltipController* tooltip_controller() {
return tooltip_controller_.get();
}
internal::TouchObserverHUD* touch_observer_hud() {
@@ -526,7 +526,7 @@ class ASH_EXPORT Shell
scoped_ptr<views::corewm::VisibilityController> visibility_controller_;
scoped_ptr<views::corewm::WindowModalityController>
window_modality_controller_;
- scoped_ptr<internal::TooltipController> tooltip_controller_;
+ scoped_ptr<views::corewm::TooltipController> tooltip_controller_;
scoped_ptr<DesktopBackgroundController> desktop_background_controller_;
scoped_ptr<PowerButtonController> power_button_controller_;
scoped_ptr<SessionStateController> session_state_controller_;
diff --git a/ash/shell/lock_view.cc b/ash/shell/lock_view.cc
index 56c0f27..16895c6 100644
--- a/ash/shell/lock_view.cc
+++ b/ash/shell/lock_view.cc
@@ -6,13 +6,13 @@
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "ash/shell/example_factory.h"
-#include "ash/tooltips/tooltip_controller.h"
#include "base/utf_string_conversions.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
#include "ui/views/controls/button/text_button.h"
+#include "ui/views/corewm/tooltip_controller.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -100,6 +100,7 @@ void CreateLockScreen() {
widget->GetNativeView()->SetName("LockView");
widget->GetNativeView()->Focus();
+ // TODO: it shouldn't be necessary to invoke UpdateTooltip() here.
Shell::GetInstance()->tooltip_controller()->UpdateTooltip(
widget->GetNativeView());
}
diff --git a/ash/tooltips/tooltip_controller_unittest.cc b/ash/tooltips/tooltip_controller_unittest.cc
index f594de4..85ded1e 100644
--- a/ash/tooltips/tooltip_controller_unittest.cc
+++ b/ash/tooltips/tooltip_controller_unittest.cc
@@ -5,7 +5,6 @@
#include "ash/display/display_controller.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
-#include "ash/tooltips/tooltip_controller.h"
#include "ash/wm/cursor_manager.h"
#include "base/utf_string_conversions.h"
#include "ui/aura/client/tooltip_client.h"
@@ -14,37 +13,26 @@
#include "ui/aura/test/event_generator.h"
#include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/text/text_elider.h"
#include "ui/gfx/font.h"
#include "ui/gfx/point.h"
+#include "ui/views/corewm/tooltip_controller.h"
+#include "ui/views/corewm/tooltip_controller_test_helper.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
+using views::corewm::TooltipController;
+using views::corewm::test::TooltipTestView;
+using views::corewm::test::TooltipControllerTestHelper;
+
+// The tests in this file exercise bits of TooltipController that are hard to
+// test outside of ash. Meaning these tests require the shell and related things
+// to be installed.
+
namespace ash {
namespace test {
namespace {
-class TooltipTestView : public views::View {
- public:
- TooltipTestView() : views::View() {
- }
-
- void set_tooltip_text(string16 tooltip_text) { tooltip_text_ = tooltip_text; }
-
- // Overridden from views::View
- virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE {
- *tooltip = tooltip_text_;
- return true;
- }
-
- private:
- string16 tooltip_text_;
-
- DISALLOW_COPY_AND_ASSIGN(TooltipTestView);
-};
-
views::Widget* CreateNewWidgetWithBoundsOn(int display,
const gfx::Rect& bounds) {
views::Widget* widget = new views::Widget;
@@ -80,8 +68,8 @@ void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
contents_view_bounds.size()));
}
-ash::internal::TooltipController* GetController() {
- return static_cast<ash::internal::TooltipController*>(
+TooltipController* GetController() {
+ return static_cast<TooltipController*>(
aura::client::GetTooltipClient(Shell::GetPrimaryRootWindow()));
}
@@ -97,43 +85,13 @@ class TooltipControllerTest : public AshTestBase {
TooltipControllerTest() {}
virtual ~TooltipControllerTest() {}
- string16 GetTooltipText() {
- return GetController()->tooltip_text_;
- }
-
- aura::Window* GetTooltipWindow() {
- return GetController()->tooltip_window_;
+ virtual void SetUp() OVERRIDE {
+ AshTestBase::SetUp();
+ helper_.reset(new TooltipControllerTestHelper(GetController()));
}
- void FireTooltipTimer() {
- GetController()->TooltipTimerFired();
- }
-
- bool IsTooltipTimerRunning() {
- return GetController()->tooltip_timer_.IsRunning();
- }
-
- void FireTooltipShownTimer() {
- GetController()->tooltip_shown_timer_.Stop();
- GetController()->TooltipShownTimerFired();
- }
-
- bool IsTooltipShownTimerRunning() {
- return GetController()->tooltip_shown_timer_.IsRunning();
- }
-
- bool IsTooltipVisible() {
- return GetController()->IsTooltipVisible();
- }
-
- void TrimTooltipToFit(string16* text,
- int* max_width,
- int* line_count,
- int x,
- int y) {
- ash::internal::TooltipController::TrimTooltipToFit(text, max_width,
- line_count, x, y);
- }
+ protected:
+ scoped_ptr<TooltipControllerTestHelper> helper_;
private:
DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest);
@@ -142,112 +100,9 @@ class TooltipControllerTest : public AshTestBase {
TEST_F(TooltipControllerTest, NonNullTooltipClient) {
EXPECT_TRUE(aura::client::GetTooltipClient(Shell::GetPrimaryRootWindow())
!= NULL);
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
- EXPECT_FALSE(IsTooltipVisible());
-}
-
-TEST_F(TooltipControllerTest, ViewTooltip) {
- scoped_ptr<views::Widget> widget(CreateNewWidgetOn(0));
- TooltipTestView* view = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view);
- view->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
- aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
- generator.MoveMouseToCenterOf(widget->GetNativeView());
-
- aura::Window* window = widget->GetNativeView();
- EXPECT_EQ(window, Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
- generator.current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
-
- // Fire tooltip timer so tooltip becomes visible.
- FireTooltipTimer();
-
- EXPECT_TRUE(IsTooltipVisible());
- generator.MoveMouseBy(1, 0);
-
- EXPECT_TRUE(IsTooltipVisible());
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
-}
-
-TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
- scoped_ptr<views::Widget> widget(CreateNewWidgetOn(0));
- TooltipTestView* view1 = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view1);
- view1->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
-
- TooltipTestView* view2 = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view2);
-
- aura::Window* window = widget->GetNativeView();
-
- // Fire tooltip timer so tooltip becomes visible.
- aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
- generator.MoveMouseRelativeTo(window,
- view1->bounds().CenterPoint());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
- for (int i = 0; i < 49; ++i) {
- generator.MoveMouseBy(1, 0);
- EXPECT_TRUE(IsTooltipVisible());
- EXPECT_EQ(window,
- Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
- generator.current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
- }
- for (int i = 0; i < 49; ++i) {
- generator.MoveMouseBy(1, 0);
- EXPECT_FALSE(IsTooltipVisible());
- EXPECT_EQ(window,
- Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
- generator.current_location()));
- string16 expected_tooltip; // = ""
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
- }
-}
-
-TEST_F(TooltipControllerTest, EnableOrDisableTooltips) {
- scoped_ptr<views::Widget> widget(CreateNewWidgetOn(0));
- TooltipTestView* view = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view);
- view->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
-
- aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
- generator.MoveMouseRelativeTo(widget->GetNativeView(),
- view->bounds().CenterPoint());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
-
- // Fire tooltip timer so tooltip becomes visible.
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
-
- // Diable tooltips and check again.
- GetController()->SetTooltipsEnabled(false);
- EXPECT_FALSE(IsTooltipVisible());
- FireTooltipTimer();
- EXPECT_FALSE(IsTooltipVisible());
-
- // Enable tooltips back and check again.
- GetController()->SetTooltipsEnabled(true);
- EXPECT_FALSE(IsTooltipVisible());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+ EXPECT_FALSE(helper_->IsTooltipVisible());
}
TEST_F(TooltipControllerTest, HideTooltipWhenCursorHidden) {
@@ -255,8 +110,8 @@ TEST_F(TooltipControllerTest, HideTooltipWhenCursorHidden) {
TooltipTestView* view = new TooltipTestView;
AddViewToWidgetAndResize(widget.get(), view);
view->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
generator.MoveMouseRelativeTo(widget->GetNativeView(),
@@ -264,220 +119,18 @@ TEST_F(TooltipControllerTest, HideTooltipWhenCursorHidden) {
string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
// Fire tooltip timer so tooltip becomes visible.
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
// Hide the cursor and check again.
ash::Shell::GetInstance()->cursor_manager()->DisableMouseEvents();
- FireTooltipTimer();
- EXPECT_FALSE(IsTooltipVisible());
+ helper_->FireTooltipTimer();
+ EXPECT_FALSE(helper_->IsTooltipVisible());
// Show the cursor and re-check.
ash::Shell::GetInstance()->cursor_manager()->EnableMouseEvents();
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
-}
-
-TEST_F(TooltipControllerTest, TrimTooltipToFitTests) {
- string16 tooltip;
- int max_width, line_count, expect_lines;
- int max_pixel_width = 400; // copied from constants in tooltip_controller.cc
- int max_lines = 10; // copied from constants in tooltip_controller.cc
- gfx::Font font = GetDefaultFont();
- size_t tooltip_len;
-
- // Error in computed size vs. expected size should not be greater than the
- // size of the longest word.
- int error_in_pixel_width = font.GetStringWidth(ASCIIToUTF16("tooltip"));
-
- // Long tooltips should wrap to next line
- tooltip.clear();
- max_width = line_count = -1;
- expect_lines = 3;
- for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
- tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
- tooltip_len = tooltip.length();
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- EXPECT_NEAR(max_pixel_width, max_width, error_in_pixel_width);
- EXPECT_EQ(expect_lines, line_count);
- EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length());
-
- // More than |max_lines| lines should get truncated at 10 lines.
- tooltip.clear();
- max_width = line_count = -1;
- expect_lines = 13;
- for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
- tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- EXPECT_NEAR(max_pixel_width, max_width, error_in_pixel_width);
- EXPECT_EQ(max_lines, line_count);
-
- // Long multi line tooltips should wrap individual lines.
- tooltip.clear();
- max_width = line_count = -1;
- expect_lines = 4;
- for (; font.GetStringWidth(tooltip) <= (expect_lines - 2) * max_pixel_width;)
- tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
- tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n"));
- tooltip_len = tooltip.length();
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- EXPECT_NEAR(max_pixel_width, max_width, error_in_pixel_width);
- EXPECT_EQ(expect_lines, line_count);
- // We may have inserted the line break above near a space which will get
- // trimmed. Hence we may be off by 1 in the final tooltip length calculation.
- EXPECT_NEAR(tooltip_len + expect_lines - 2, tooltip.length(), 1);
-
-#if !defined(OS_WIN)
- // Tooltip with really long word gets elided.
- tooltip.clear();
- max_width = line_count = -1;
- tooltip = UTF8ToUTF16(std::string('a', max_pixel_width));
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- EXPECT_NEAR(max_pixel_width, max_width, 5);
- EXPECT_EQ(1, line_count);
- EXPECT_EQ(ui::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font,
- max_pixel_width, ui::ELIDE_AT_END), tooltip);
-#endif
-
- // Normal small tooltip should stay as is.
- tooltip.clear();
- max_width = line_count = -1;
- tooltip = ASCIIToUTF16("Small Tooltip");
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tooltip")), max_width);
- EXPECT_EQ(1, line_count);
- EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip);
-
- // Normal small multi-line tooltip should stay as is.
- tooltip.clear();
- max_width = line_count = -1;
- tooltip = ASCIIToUTF16("Multi line\nTooltip");
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- int expected_width = font.GetStringWidth(ASCIIToUTF16("Multi line"));
- expected_width = std::max(expected_width,
- font.GetStringWidth(ASCIIToUTF16("Tooltip")));
- EXPECT_EQ(expected_width, max_width);
- EXPECT_EQ(2, line_count);
- EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip);
-
- // Whitespaces in tooltips are preserved.
- tooltip.clear();
- max_width = line_count = -1;
- tooltip = ASCIIToUTF16("Small Tool t\tip");
- TrimTooltipToFit(&tooltip, &max_width, &line_count, 0, 0);
- EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tool t\tip")), max_width);
- EXPECT_EQ(1, line_count);
- EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip);
-}
-
-TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
- scoped_ptr<views::Widget> widget(CreateNewWidgetOn(0));
- TooltipTestView* view1 = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view1);
- view1->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1"));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
-
- TooltipTestView* view2 = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view2);
- view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 2"));
-
- aura::Window* window = widget->GetNativeView();
-
- // Fire tooltip timer so tooltip becomes visible.
- aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
- generator.MoveMouseRelativeTo(window,
- view1->bounds().CenterPoint());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
- EXPECT_TRUE(IsTooltipShownTimerRunning());
-
- generator.PressKey(ui::VKEY_1, 0);
- EXPECT_FALSE(IsTooltipVisible());
- EXPECT_FALSE(IsTooltipTimerRunning());
- EXPECT_FALSE(IsTooltipShownTimerRunning());
-
- // Moving the mouse inside |view1| should not change the state of the tooltip
- // or the timers.
- for (int i = 0; i < 49; i++) {
- generator.MoveMouseBy(1, 0);
- EXPECT_FALSE(IsTooltipVisible());
- EXPECT_FALSE(IsTooltipTimerRunning());
- EXPECT_FALSE(IsTooltipShownTimerRunning());
- EXPECT_EQ(window,
- Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
- generator.current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
- }
-
- // Now we move the mouse on to |view2|. It should re-start the tooltip timer.
- generator.MoveMouseBy(1, 0);
- EXPECT_TRUE(IsTooltipTimerRunning());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
- EXPECT_TRUE(IsTooltipShownTimerRunning());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
-}
-
-TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
- scoped_ptr<views::Widget> widget(CreateNewWidgetOn(0));
- TooltipTestView* view1 = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view1);
- view1->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1"));
- EXPECT_EQ(string16(), GetTooltipText());
- EXPECT_EQ(NULL, GetTooltipWindow());
-
- TooltipTestView* view2 = new TooltipTestView;
- AddViewToWidgetAndResize(widget.get(), view2);
- view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 2"));
-
- aura::Window* window = widget->GetNativeView();
-
- // Fire tooltip timer so tooltip becomes visible.
- aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
- generator.MoveMouseRelativeTo(window,
- view1->bounds().CenterPoint());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
- EXPECT_TRUE(IsTooltipShownTimerRunning());
-
- FireTooltipShownTimer();
- EXPECT_FALSE(IsTooltipVisible());
- EXPECT_FALSE(IsTooltipTimerRunning());
- EXPECT_FALSE(IsTooltipShownTimerRunning());
-
- // Moving the mouse inside |view1| should not change the state of the tooltip
- // or the timers.
- for (int i = 0; i < 49; ++i) {
- generator.MoveMouseBy(1, 0);
- EXPECT_FALSE(IsTooltipVisible());
- EXPECT_FALSE(IsTooltipTimerRunning());
- EXPECT_FALSE(IsTooltipShownTimerRunning());
- EXPECT_EQ(window,
- Shell::GetPrimaryRootWindow()->GetEventHandlerForPoint(
- generator.current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
- }
-
- // Now we move the mouse on to |view2|. It should re-start the tooltip timer.
- generator.MoveMouseBy(1, 0);
- EXPECT_TRUE(IsTooltipTimerRunning());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
- EXPECT_TRUE(IsTooltipShownTimerRunning());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, GetTooltipText());
- EXPECT_EQ(window, GetTooltipWindow());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
}
#if defined(OS_WIN)
@@ -510,8 +163,8 @@ TEST_F(TooltipControllerTest, MAYBE_TooltipsOnMultiDisplayShouldNotCrash) {
aura::test::EventGenerator generator(root_windows[1]);
generator.MoveMouseRelativeTo(widget2->GetNativeView(),
view2->bounds().CenterPoint());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
// Get rid of secondary display. This destroy's the tooltip's aura window. If
// we have handled this case, we will not crash in the following statement.
@@ -520,7 +173,7 @@ TEST_F(TooltipControllerTest, MAYBE_TooltipsOnMultiDisplayShouldNotCrash) {
// TODO(cpu): Detangle the window destruction notification. Currently
// the TooltipController::OnWindowDestroyed is not being called then the
// display is torn down so the tooltip is is still there.
- EXPECT_FALSE(IsTooltipVisible());
+ EXPECT_FALSE(helper_->IsTooltipVisible());
#endif
EXPECT_EQ(widget2->GetNativeView()->GetRootWindow(), root_windows[0]);
@@ -529,8 +182,8 @@ TEST_F(TooltipControllerTest, MAYBE_TooltipsOnMultiDisplayShouldNotCrash) {
aura::test::EventGenerator generator1(root_windows[0]);
generator1.MoveMouseRelativeTo(widget1->GetNativeView(),
view1->bounds().CenterPoint());
- FireTooltipTimer();
- EXPECT_TRUE(IsTooltipVisible());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
}
} // namespace test
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index 6ddbdcf9..77976f5 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -798,13 +798,13 @@ std::string LoginUtilsImpl::GetOffTheRecordCommandLine(
::switches::kUseExynosVda,
ash::switches::kAshTouchHud,
ash::switches::kAuraLegacyPowerButton,
- ash::switches::kAuraNoShadows,
ash::switches::kAshEnableNewNetworkStatusArea,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnablePartialSwap,
chromeos::switches::kDbusStub,
gfx::switches::kEnableBrowserTextSubpixelPositioning,
gfx::switches::kEnableWebkitTextSubpixelPositioning,
+ views::corewm::switches::kNoDropShadows,
views::corewm::switches::kWindowAnimationsDisabled,
};
command_line->CopySwitchesFrom(base_command_line,
diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc
index 824c138..60c16e7 100644
--- a/chrome/browser/ui/views/chrome_views_delegate.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate.cc
@@ -217,7 +217,7 @@ void ChromeViewsDelegate::OnBeforeWidgetInit(
} else if (params->parent &&
params->type != views::Widget::InitParams::TYPE_MENU) {
params->native_widget = new views::NativeWidgetAura(delegate);
- } else {
+ } else if (params->type != views::Widget::InitParams::TYPE_TOOLTIP) {
// TODO(erg): Once we've threaded context to everywhere that needs it, we
// should remove this check here.
gfx::NativeView to_check =
diff --git a/ui/views/corewm/corewm_switches.cc b/ui/views/corewm/corewm_switches.cc
index ac0ffab..450738e 100644
--- a/ui/views/corewm/corewm_switches.cc
+++ b/ui/views/corewm/corewm_switches.cc
@@ -18,6 +18,8 @@ const char kDisableFocusController[] = "disable-focus-controller";
const char kDisableFocusControllerOnDesktop[] =
"disable-focus-controller-on-desktop";
+const char kNoDropShadows[] = "aura-no-shadows";
+
// If present animations are disabled.
const char kWindowAnimationsDisabled[] =
"views-corewm-window-animations-disabled";
diff --git a/ui/views/corewm/corewm_switches.h b/ui/views/corewm/corewm_switches.h
index a9f452d..a78088c 100644
--- a/ui/views/corewm/corewm_switches.h
+++ b/ui/views/corewm/corewm_switches.h
@@ -17,6 +17,7 @@ namespace switches {
// see chromeos::LoginUtil::GetOffTheRecordCommandLine().)
// Please keep alphabetized.
+VIEWS_EXPORT extern const char kNoDropShadows[];
VIEWS_EXPORT extern const char kWindowAnimationsDisabled[];
} // namespace switches
diff --git a/ash/tooltips/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index c8bde19..0f63063 100644
--- a/ash/tooltips/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -2,18 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ash/tooltips/tooltip_controller.h"
+#include "ui/views/corewm/tooltip_controller.h"
#include <vector>
-#include "ash/ash_switches.h"
-#include "ash/shell.h"
-#include "ash/wm/coordinate_conversion.h"
-#include "ash/wm/cursor_manager.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/string_split.h"
#include "base/time.h"
+#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
@@ -28,6 +25,7 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
+#include "ui/views/corewm/corewm_switches.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
@@ -66,22 +64,14 @@ gfx::Font GetDefaultFont() {
ui::ResourceBundle::BaseFont);
}
-int GetMaxWidth(int x, int y) {
- // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure
- // out a way to merge.
- gfx::Rect display_bounds = ash::Shell::GetScreen()->GetDisplayNearestPoint(
- gfx::Point(x, y)).bounds();
- return (display_bounds.width() + 1) / 2;
-}
-
// Creates a widget of type TYPE_TOOLTIP
-views::Widget* CreateTooltip(const gfx::Point location) {
+views::Widget* CreateTooltip(aura::Window* tooltip_window) {
views::Widget* widget = new views::Widget;
views::Widget::InitParams params;
// For aura, since we set the type to TOOLTIP_TYPE, the widget will get
// auto-parented to the MenuAndTooltipsContainer.
params.type = views::Widget::InitParams::TYPE_TOOLTIP;
- params.context = ash::wm::GetRootWindowAt(location);
+ params.context = tooltip_window;
DCHECK(params.context);
params.keep_on_top = true;
params.accept_events = false;
@@ -91,17 +81,18 @@ views::Widget* CreateTooltip(const gfx::Point location) {
} // namespace
-namespace ash {
-namespace internal {
+namespace views {
+namespace corewm {
// Displays a widget with tooltip using a views::Label.
class TooltipController::Tooltip : public views::WidgetObserver {
public:
Tooltip(TooltipController* controller)
- : controller_(controller), widget_(NULL) {
+ : controller_(controller),
+ widget_(NULL) {
label_.set_background(
views::Background::CreateSolidBackground(kTooltipBackground));
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAuraNoShadows)) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDropShadows)) {
label_.set_border(
views::Border::CreateSolidBorder(kTooltipBorderWidth,
kTooltipBorder));
@@ -117,26 +108,31 @@ class TooltipController::Tooltip : public views::WidgetObserver {
}
// Updates the text on the tooltip and resizes to fit.
- void SetText(string16 tooltip_text, gfx::Point location) {
+ void SetText(aura::Window* window,
+ const string16& tooltip_text,
+ const gfx::Point& location) {
int max_width, line_count;
- TrimTooltipToFit(&tooltip_text, &max_width, &line_count,
- location.x(), location.y());
- label_.SetText(tooltip_text);
+ string16 trimmed_text(tooltip_text);
+ controller_->TrimTooltipToFit(
+ controller_->GetMaxWidth(location), &trimmed_text, &max_width,
+ &line_count);
+ label_.SetText(trimmed_text);
int width = max_width + 2 * kTooltipHorizontalPadding;
int height = label_.GetPreferredSize().height() +
2 * kTooltipVerticalPadding;
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAuraNoShadows)) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDropShadows)) {
width += 2 * kTooltipBorderWidth;
height += 2 * kTooltipBorderWidth;
}
+ CreateWidgetIfNecessary(window);
SetTooltipBounds(location, width, height);
}
// Shows the tooltip.
void Show() {
- GetWidget()->Show();
+ if (widget_)
+ widget_->Show();
}
// Hides the tooltip.
@@ -146,7 +142,7 @@ class TooltipController::Tooltip : public views::WidgetObserver {
}
bool IsVisible() {
- return widget_? widget_->IsVisible() : false;
+ return widget_ && widget_->IsVisible();
}
// Overriden from views::WidgetObserver.
@@ -156,21 +152,16 @@ class TooltipController::Tooltip : public views::WidgetObserver {
}
private:
- views::Label label_;
- TooltipController* controller_;
- views::Widget* widget_;
-
// Adjusts the bounds given by the arguments to fit inside the desktop
// and applies the adjusted bounds to the label_.
- void SetTooltipBounds(gfx::Point mouse_pos,
+ void SetTooltipBounds(const gfx::Point& mouse_pos,
int tooltip_width,
int tooltip_height) {
gfx::Rect tooltip_rect(mouse_pos.x(), mouse_pos.y(), tooltip_width,
tooltip_height);
tooltip_rect.Offset(kCursorOffsetX, kCursorOffsetY);
- gfx::Rect display_bounds = Shell::GetScreen()->GetDisplayNearestPoint(
- tooltip_rect.origin()).bounds();
+ gfx::Rect display_bounds = controller_->GetBoundsForTooltip(mouse_pos);
// If tooltip is out of bounds on the x axis, we simply shift it
// horizontally by the offset.
@@ -185,25 +176,29 @@ class TooltipController::Tooltip : public views::WidgetObserver {
tooltip_rect.set_y(mouse_pos.y() - tooltip_height);
tooltip_rect.AdjustToFit(display_bounds);
- GetWidget()->SetBounds(tooltip_rect);
+ widget_->SetBounds(tooltip_rect);
}
- views::Widget* GetWidget() {
- if (!widget_) {
- widget_ = CreateTooltip(controller_->mouse_location());
- widget_->SetContentsView(&label_);
- widget_->AddObserver(this);
- }
- return widget_;
+ void CreateWidgetIfNecessary(aura::Window* tooltip_window) {
+ if (widget_)
+ return;
+ widget_ = CreateTooltip(tooltip_window);
+ widget_->SetContentsView(&label_);
+ widget_->AddObserver(this);
}
+
+ views::Label label_;
+ TooltipController* controller_;
+ views::Widget* widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(Tooltip);
};
////////////////////////////////////////////////////////////////////////////////
// TooltipController public:
-TooltipController::TooltipController(
- aura::client::DragDropClient* drag_drop_client)
- : drag_drop_client_(drag_drop_client),
+TooltipController::TooltipController(gfx::ScreenType screen_type)
+ : screen_type_(screen_type),
tooltip_window_(NULL),
tooltip_window_at_mouse_press_(NULL),
mouse_pressed_(false),
@@ -211,7 +206,6 @@ TooltipController::TooltipController(
tooltip_timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs),
this, &TooltipController::TooltipTimerFired);
- DCHECK(drag_drop_client_);
}
TooltipController::~TooltipController() {
@@ -272,10 +266,13 @@ void TooltipController::OnMouseEvent(ui::MouseEvent* event) {
UpdateIfRequired();
break;
case ui::ET_MOUSE_PRESSED:
- mouse_pressed_ = true;
- tooltip_window_at_mouse_press_ = target;
- if (target)
- tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target);
+ if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) {
+ // We don't get a release for non-client areas.
+ mouse_pressed_ = true;
+ tooltip_window_at_mouse_press_ = target;
+ if (target)
+ tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target);
+ }
GetTooltip()->Hide();
break;
case ui::ET_MOUSE_RELEASED:
@@ -320,13 +317,37 @@ void TooltipController::OnWindowDestroyed(aura::Window* window) {
////////////////////////////////////////////////////////////////////////////////
// TooltipController private:
+int TooltipController::GetMaxWidth(const gfx::Point& location) const {
+ // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure
+ // out a way to merge.
+ gfx::Rect display_bounds = GetBoundsForTooltip(location);
+ return (display_bounds.width() + 1) / 2;
+}
+
+gfx::Rect TooltipController::GetBoundsForTooltip(
+ const gfx::Point& origin) const {
+ DCHECK(tooltip_window_);
+ gfx::Rect widget_bounds;
+ // For Desktop aura we constrain the tooltip to the bounds of the Widget
+ // (which comes from the RootWindow).
+ if (screen_type_ == gfx::SCREEN_TYPE_NATIVE &&
+ gfx::SCREEN_TYPE_NATIVE != gfx::SCREEN_TYPE_ALTERNATE) {
+ aura::RootWindow* root = tooltip_window_->GetRootWindow();
+ widget_bounds = gfx::Rect(root->GetHostOrigin(), root->GetHostSize());
+ }
+ gfx::Screen* screen = gfx::Screen::GetScreenByType(screen_type_);
+ gfx::Rect bounds(screen->GetDisplayNearestPoint(origin).bounds());
+ if (!widget_bounds.IsEmpty())
+ bounds.Intersect(widget_bounds);
+ return bounds;
+}
+
// static
-void TooltipController::TrimTooltipToFit(string16* text,
- int* max_width,
- int* line_count,
- int x,
- int y) {
- *max_width = 0;
+void TooltipController::TrimTooltipToFit(int max_width,
+ string16* text,
+ int* width,
+ int* line_count) {
+ *width = 0;
*line_count = 0;
// Clamp the tooltip length to kMaxTooltipLength so that we don't
@@ -335,7 +356,7 @@ void TooltipController::TrimTooltipToFit(string16* text,
*text = text->substr(0, kMaxTooltipLength);
// Determine the available width for the tooltip.
- int available_width = std::min(kTooltipMaxWidthPixels, GetMaxWidth(x, y));
+ int available_width = std::min(kTooltipMaxWidthPixels, max_width);
std::vector<string16> lines;
base::SplitString(*text, '\n', &lines);
@@ -391,10 +412,10 @@ void TooltipController::TrimTooltipToFit(string16* text,
// very long word, line_width is greater than the available_width. In such
// case, we simply truncate at available_width and add ellipses at the end.
if (line_width > available_width) {
- *max_width = available_width;
+ *width = available_width;
result.append(ui::ElideText(*l, font, available_width, ui::ELIDE_AT_END));
} else {
- *max_width = std::max(*max_width, line_width);
+ *width = std::max(*width, line_width);
result.append(*l);
}
}
@@ -416,7 +437,7 @@ void TooltipController::TooltipShownTimerFired() {
void TooltipController::UpdateIfRequired() {
if (!tooltips_enabled_ || mouse_pressed_ || IsDragDropInProgress() ||
- !ash::Shell::GetInstance()->cursor_manager()->IsCursorVisible()) {
+ !IsCursorVisible()) {
GetTooltip()->Hide();
return;
}
@@ -447,14 +468,19 @@ void TooltipController::UpdateIfRequired() {
if (tooltip_text_.empty()) {
GetTooltip()->Hide();
} else {
- string16 tooltip_text(tooltip_text_);
gfx::Point widget_loc = curr_mouse_loc_ +
tooltip_window_->GetBoundsInScreen().OffsetFromOrigin();
- GetTooltip()->SetText(tooltip_text, widget_loc);
- GetTooltip()->Show();
- tooltip_shown_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kTooltipShownTimeoutMs),
- this, &TooltipController::TooltipShownTimerFired);
+ gfx::Rect bounds(GetBoundsForTooltip(widget_loc));
+ if (bounds.IsEmpty()) {
+ tooltip_text_.clear();
+ GetTooltip()->Hide();
+ } else {
+ GetTooltip()->SetText(tooltip_window_, tooltip_text_, widget_loc);
+ GetTooltip()->Show();
+ tooltip_shown_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kTooltipShownTimeoutMs),
+ this, &TooltipController::TooltipShownTimerFired);
+ }
}
}
}
@@ -464,7 +490,11 @@ bool TooltipController::IsTooltipVisible() {
}
bool TooltipController::IsDragDropInProgress() {
- return drag_drop_client_->IsDragDropInProgress();
+ if (!tooltip_window_)
+ return false;
+ aura::client::DragDropClient* client =
+ aura::client::GetDragDropClient(tooltip_window_->GetRootWindow());
+ return client && client->IsDragDropInProgress();
}
TooltipController::Tooltip* TooltipController::GetTooltip() {
@@ -473,5 +503,17 @@ TooltipController::Tooltip* TooltipController::GetTooltip() {
return tooltip_.get();
}
-} // namespace internal
-} // namespace ash
+bool TooltipController::IsCursorVisible() {
+ if (!tooltip_window_)
+ return false;
+ aura::RootWindow* root = tooltip_window_->GetRootWindow();
+ if (!root)
+ return false;
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(root);
+ // |cursor_client| may be NULL in tests, treat NULL as always visible.
+ return !cursor_client || cursor_client->IsCursorVisible();
+}
+
+} // namespace corewm
+} // namespace views
diff --git a/ash/tooltips/tooltip_controller.h b/ui/views/corewm/tooltip_controller.h
index 3022aee..efce0ac 100644
--- a/ash/tooltips/tooltip_controller.h
+++ b/ui/views/corewm/tooltip_controller.h
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef ASH_TOOLTIPS_TOOLTIP_CONTROLLER_H_
-#define ASH_TOOLTIPS_TOOLTIP_CONTROLLER_H_
+#ifndef UI_VIEWS_COREWM_TOOLTIP_CONTROLLER_H_
+#define UI_VIEWS_COREWM_TOOLTIP_CONTROLLER_H_
-#include "ash/ash_export.h"
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "base/timer.h"
@@ -13,28 +12,26 @@
#include "ui/aura/window_observer.h"
#include "ui/base/events/event_handler.h"
#include "ui/gfx/point.h"
+#include "ui/gfx/screen_type_delegate.h"
+#include "ui/views/views_export.h"
namespace aura {
class Window;
-namespace client {
-class DragDropClient;
-}
}
-namespace ash {
+namespace views {
+namespace corewm {
namespace test {
-class TooltipControllerTest;
+class TooltipControllerTestHelper;
} // namespace test
-namespace internal {
-
// TooltipController provides tooltip functionality for aura shell.
-class ASH_EXPORT TooltipController : public aura::client::TooltipClient,
- public ui::EventHandler,
- public aura::WindowObserver {
+class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
+ public ui::EventHandler,
+ public aura::WindowObserver {
public:
- explicit TooltipController(aura::client::DragDropClient* drag_drop_client);
+ explicit TooltipController(gfx::ScreenType screen_type);
virtual ~TooltipController();
// Overridden from aura::client::TooltipClient.
@@ -50,22 +47,28 @@ class ASH_EXPORT TooltipController : public aura::client::TooltipClient,
// Overridden from aura::WindowObserver.
virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
- gfx::Point mouse_location() const { return curr_mouse_loc_; }
+ const gfx::Point& mouse_location() const { return curr_mouse_loc_; }
private:
- friend class ash::test::TooltipControllerTest;
+ friend class test::TooltipControllerTestHelper;
class Tooltip;
- // Trims the tooltip to fit, setting |text| to the clipped result,
- // |max_width| to the width (in pixels) of the clipped text and |line_count|
- // to the number of lines of text in the tooltip. |x| and |y| give the
- // location of the tooltip in screen coordinates.
- static void TrimTooltipToFit(string16* text,
- int* max_width,
- int* line_count,
- int x,
- int y);
+ // Returns the max width of the tooltip when shown at the specified location.
+ int GetMaxWidth(const gfx::Point& location) const;
+
+ // Returns the bounds to fit the tooltip in.
+ gfx::Rect GetBoundsForTooltip(const gfx::Point& origin) const;
+
+ // Trims the tooltip to fit in the width |max_width|, setting |text| to the
+ // clipped result, |width| to the width (in pixels) of the clipped text
+ // and |line_count| to the number of lines of text in the tooltip. |x| and |y|
+ // give the location of the tooltip in screen coordinates. |max_width| comes
+ // from GetMaxWidth().
+ static void TrimTooltipToFit(int max_width,
+ string16* text,
+ int* width,
+ int* line_count);
void TooltipTimerFired();
void TooltipShownTimerFired();
@@ -83,7 +86,10 @@ class ASH_EXPORT TooltipController : public aura::client::TooltipClient,
// be initialized with appropriate drop shadows.
Tooltip* GetTooltip();
- aura::client::DragDropClient* drag_drop_client_;
+ // Returns true if the cursor is visible.
+ bool IsCursorVisible();
+
+ const gfx::ScreenType screen_type_;
aura::Window* tooltip_window_;
string16 tooltip_text_;
@@ -108,7 +114,7 @@ class ASH_EXPORT TooltipController : public aura::client::TooltipClient,
DISALLOW_COPY_AND_ASSIGN(TooltipController);
};
-} // namespace internal
-} // namespace ash
+} // namespace corewm
+} // namespace views
-#endif // ASH_TOOLTIPS_TOOLTIP_CONTROLLER_H_
+#endif // UI_VIEWS_COREWM_TOOLTIP_CONTROLLER_H_
diff --git a/ui/views/corewm/tooltip_controller_test_helper.cc b/ui/views/corewm/tooltip_controller_test_helper.cc
new file mode 100644
index 0000000..9a2f06f
--- /dev/null
+++ b/ui/views/corewm/tooltip_controller_test_helper.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 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.
+
+#include "ui/views/corewm/tooltip_controller_test_helper.h"
+
+#include "ui/aura/window.h"
+#include "ui/views/corewm/tooltip_controller.h"
+
+namespace views {
+namespace corewm {
+namespace test {
+
+TooltipControllerTestHelper::TooltipControllerTestHelper(
+ TooltipController* controller)
+ : controller_(controller) {
+}
+
+TooltipControllerTestHelper::~TooltipControllerTestHelper() {
+}
+
+string16 TooltipControllerTestHelper::GetTooltipText() {
+ return controller_->tooltip_text_;
+}
+
+aura::Window* TooltipControllerTestHelper::GetTooltipWindow() {
+ return controller_->tooltip_window_;
+}
+
+void TooltipControllerTestHelper::FireTooltipTimer() {
+ controller_->TooltipTimerFired();
+}
+
+bool TooltipControllerTestHelper::IsTooltipTimerRunning() {
+ return controller_->tooltip_timer_.IsRunning();
+}
+
+void TooltipControllerTestHelper::FireTooltipShownTimer() {
+ controller_->tooltip_shown_timer_.Stop();
+ controller_->TooltipShownTimerFired();
+}
+
+bool TooltipControllerTestHelper::IsTooltipShownTimerRunning() {
+ return controller_->tooltip_shown_timer_.IsRunning();
+}
+
+bool TooltipControllerTestHelper::IsTooltipVisible() {
+ return controller_->IsTooltipVisible();
+}
+
+// static
+void TooltipControllerTestHelper::TrimTooltipToFit(int max_width,
+ string16* text,
+ int* width,
+ int* line_count) {
+ TooltipController::TrimTooltipToFit(max_width, text, width, line_count);
+}
+
+TooltipTestView::TooltipTestView() {
+}
+
+TooltipTestView::~TooltipTestView() {
+}
+
+bool TooltipTestView::GetTooltipText(const gfx::Point& p,
+ string16* tooltip) const {
+ *tooltip = tooltip_text_;
+ return true;
+}
+
+} // namespace test
+} // namespace corewm
+} // namespace views
diff --git a/ui/views/corewm/tooltip_controller_test_helper.h b/ui/views/corewm/tooltip_controller_test_helper.h
new file mode 100644
index 0000000..9c438a0
--- /dev/null
+++ b/ui/views/corewm/tooltip_controller_test_helper.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2013 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_COREWM_TOOLTIP_CONTROLLER_TEST_HELPER_H_
+#define UI_VIEWS_COREWM_TOOLTIP_CONTROLLER_TEST_HELPER_H_
+
+#include "base/logging.h"
+#include "base/string16.h"
+#include "ui/views/view.h"
+#include "ui/views/views_export.h"
+
+namespace aura {
+class Window;
+}
+
+namespace views {
+namespace corewm {
+
+class TooltipController;
+
+namespace test {
+
+// TooltipControllerTestHelper provides access to TooltipControllers private
+// state.
+class TooltipControllerTestHelper {
+ public:
+ explicit TooltipControllerTestHelper(TooltipController* controller);
+ ~TooltipControllerTestHelper();
+
+ TooltipController* controller() { return controller_; }
+
+ // These are mostly cover methods for TooltipController private methods.
+ string16 GetTooltipText();
+ aura::Window* GetTooltipWindow();
+ void FireTooltipTimer();
+ bool IsTooltipTimerRunning();
+ void FireTooltipShownTimer();
+ bool IsTooltipShownTimerRunning();
+ bool IsTooltipVisible();
+ static void TrimTooltipToFit(int max_width,
+ string16* text,
+ int* width,
+ int* line_count);
+
+ private:
+ TooltipController* controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(TooltipControllerTestHelper);
+};
+
+// Trivial View subclass that lets you set the tooltip text.
+class TooltipTestView : public views::View {
+ public:
+ TooltipTestView();
+ virtual ~TooltipTestView();
+
+ void set_tooltip_text(string16 tooltip_text) { tooltip_text_ = tooltip_text; }
+
+ // Overridden from views::View
+ virtual bool GetTooltipText(const gfx::Point& p,
+ string16* tooltip) const OVERRIDE;
+
+ private:
+ string16 tooltip_text_;
+
+ DISALLOW_COPY_AND_ASSIGN(TooltipTestView);
+};
+
+
+} // namespace test
+} // namespace corewm
+} // namespace views
+
+#endif // UI_VIEWS_COREWM_TOOLTIP_CONTROLLER_TEST_HELPER_H_
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
new file mode 100644
index 0000000..a4410c0
--- /dev/null
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -0,0 +1,414 @@
+// Copyright (c) 2013 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.
+
+#include "ui/views/corewm/tooltip_controller.h"
+
+#include "base/utf_string_conversions.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/tooltip_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/text/text_elider.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/point.h"
+#include "ui/views/corewm/tooltip_controller_test_helper.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/scoped_ole_initializer.h"
+#endif
+#if !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#endif
+
+namespace views {
+namespace corewm {
+namespace test {
+namespace {
+
+views::Widget* CreateWidget(aura::RootWindow* root) {
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
+ params.accept_events = true;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+#if defined(OS_CHROMEOS)
+ params.parent = root;
+#else
+ params.native_widget = new DesktopNativeWidgetAura(widget);
+#endif
+ params.bounds = gfx::Rect(0, 0, 200, 100);
+ widget->Init(params);
+ widget->Show();
+ return widget;
+}
+
+gfx::Font GetDefaultFont() {
+ return ui::ResourceBundle::GetSharedInstance().GetFont(
+ ui::ResourceBundle::BaseFont);
+}
+
+TooltipController* GetController(Widget* widget) {
+ return static_cast<TooltipController*>(
+ aura::client::GetTooltipClient(
+ widget->GetNativeWindow()->GetRootWindow()));
+}
+
+} // namespace
+
+class TooltipControllerTest : public aura::test::AuraTestBase {
+ public:
+ TooltipControllerTest() : view_(NULL) {}
+ virtual ~TooltipControllerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ aura::test::AuraTestBase::SetUp();
+#if defined(OS_CHROMEOS)
+ controller_.reset(new TooltipController(gfx::SCREEN_TYPE_ALTERNATE));
+ root_window()->AddPreTargetHandler(controller_.get());
+ SetTooltipClient(root_window(), controller_.get());
+#endif
+ widget_.reset(CreateWidget(root_window()));
+ widget_->SetContentsView(new View);
+ view_ = new TooltipTestView;
+ widget_->GetContentsView()->AddChildView(view_);
+ view_->SetBoundsRect(widget_->GetContentsView()->GetLocalBounds());
+ helper_.reset(new TooltipControllerTestHelper(
+ GetController(widget_.get())));
+ generator_.reset(new aura::test::EventGenerator(GetRootWindow()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+#if defined(OS_CHROMEOS)
+ root_window()->RemovePreTargetHandler(controller_.get());
+ SetTooltipClient(root_window(), NULL);
+ controller_.reset();
+#endif
+ generator_.reset();
+ helper_.reset();
+ widget_.reset();
+ aura::test::AuraTestBase::TearDown();
+ }
+
+ protected:
+ aura::Window* GetWindow() {
+ return widget_->GetNativeWindow();
+ }
+
+ aura::RootWindow* GetRootWindow() {
+ return GetWindow()->GetRootWindow();
+ }
+
+ TooltipTestView* PrepareSecondView() {
+ TooltipTestView* view2 = new TooltipTestView;
+ widget_->GetContentsView()->AddChildView(view2);
+ view_->SetBounds(0, 0, 100, 100);
+ view2->SetBounds(100, 0, 100, 100);
+ return view2;
+ }
+
+ scoped_ptr<views::Widget> widget_;
+ TooltipTestView* view_;
+ scoped_ptr<TooltipControllerTestHelper> helper_;
+ scoped_ptr<aura::test::EventGenerator> generator_;
+
+ private:
+ scoped_ptr<TooltipController> controller_;
+#if defined(OS_WIN)
+ ui::ScopedOleInitializer ole_initializer_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest);
+};
+
+TEST_F(TooltipControllerTest, ViewTooltip) {
+ view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+ generator_->MoveMouseToCenterOf(GetWindow());
+
+ EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint(
+ generator_->current_location()));
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
+
+ // Fire tooltip timer so tooltip becomes visible.
+ helper_->FireTooltipTimer();
+
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ generator_->MoveMouseBy(1, 0);
+
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
+}
+
+TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
+ view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+
+ PrepareSecondView();
+ aura::Window* window = GetWindow();
+ aura::RootWindow* root_window = GetRootWindow();
+
+ // Fire tooltip timer so tooltip becomes visible.
+ generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ for (int i = 0; i < 49; ++i) {
+ generator_->MoveMouseBy(1, 0);
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(window, root_window->GetEventHandlerForPoint(
+ generator_->current_location()));
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(window, helper_->GetTooltipWindow());
+ }
+ for (int i = 0; i < 49; ++i) {
+ generator_->MoveMouseBy(1, 0);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_EQ(window, root_window->GetEventHandlerForPoint(
+ generator_->current_location()));
+ string16 expected_tooltip; // = ""
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(window, helper_->GetTooltipWindow());
+ }
+}
+
+TEST_F(TooltipControllerTest, EnableOrDisableTooltips) {
+ view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+
+ generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint());
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+
+ // Fire tooltip timer so tooltip becomes visible.
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+
+ // Diable tooltips and check again.
+ helper_->controller()->SetTooltipsEnabled(false);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ helper_->FireTooltipTimer();
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+
+ // Enable tooltips back and check again.
+ helper_->controller()->SetTooltipsEnabled(true);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+}
+
+TEST_F(TooltipControllerTest, TrimTooltipToFitTests) {
+ const int max_width = 4000;
+ string16 tooltip;
+ int width, line_count, expect_lines;
+ int max_pixel_width = 400; // copied from constants in tooltip_controller.cc
+ int max_lines = 10; // copied from constants in tooltip_controller.cc
+ gfx::Font font = GetDefaultFont();
+ size_t tooltip_len;
+
+ // Error in computed size vs. expected size should not be greater than the
+ // size of the longest word.
+ int error_in_pixel_width = font.GetStringWidth(ASCIIToUTF16("tooltip"));
+
+ // Long tooltips should wrap to next line
+ tooltip.clear();
+ width = line_count = -1;
+ expect_lines = 3;
+ for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
+ tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
+ tooltip_len = tooltip.length();
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width);
+ EXPECT_EQ(expect_lines, line_count);
+ EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length());
+
+ // More than |max_lines| lines should get truncated at 10 lines.
+ tooltip.clear();
+ width = line_count = -1;
+ expect_lines = 13;
+ for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
+ tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width);
+ EXPECT_EQ(max_lines, line_count);
+
+ // Long multi line tooltips should wrap individual lines.
+ tooltip.clear();
+ width = line_count = -1;
+ expect_lines = 4;
+ for (; font.GetStringWidth(tooltip) <= (expect_lines - 2) * max_pixel_width;)
+ tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
+ tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n"));
+ tooltip_len = tooltip.length();
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width);
+ EXPECT_EQ(expect_lines, line_count);
+ // We may have inserted the line break above near a space which will get
+ // trimmed. Hence we may be off by 1 in the final tooltip length calculation.
+ EXPECT_NEAR(tooltip_len + expect_lines - 2, tooltip.length(), 1);
+
+#if !defined(OS_WIN)
+ // Tooltip with really long word gets elided.
+ tooltip.clear();
+ width = line_count = -1;
+ tooltip = UTF8ToUTF16(std::string('a', max_pixel_width));
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ EXPECT_NEAR(max_pixel_width, width, 5);
+ EXPECT_EQ(1, line_count);
+ EXPECT_EQ(ui::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font,
+ max_pixel_width, ui::ELIDE_AT_END), tooltip);
+#endif
+
+ // Normal small tooltip should stay as is.
+ tooltip.clear();
+ width = line_count = -1;
+ tooltip = ASCIIToUTF16("Small Tooltip");
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tooltip")), width);
+ EXPECT_EQ(1, line_count);
+ EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip);
+
+ // Normal small multi-line tooltip should stay as is.
+ tooltip.clear();
+ width = line_count = -1;
+ tooltip = ASCIIToUTF16("Multi line\nTooltip");
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ int expected_width = font.GetStringWidth(ASCIIToUTF16("Multi line"));
+ expected_width = std::max(expected_width,
+ font.GetStringWidth(ASCIIToUTF16("Tooltip")));
+ EXPECT_EQ(expected_width, width);
+ EXPECT_EQ(2, line_count);
+ EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip);
+
+ // Whitespaces in tooltips are preserved.
+ tooltip.clear();
+ width = line_count = -1;
+ tooltip = ASCIIToUTF16("Small Tool t\tip");
+ TooltipControllerTestHelper::TrimTooltipToFit(
+ max_width, &tooltip, &width, &line_count);
+ EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tool t\tip")), width);
+ EXPECT_EQ(1, line_count);
+ EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip);
+}
+
+TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
+ view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1"));
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+
+ TooltipTestView* view2 = PrepareSecondView();
+ view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 2"));
+
+ aura::Window* window = GetWindow();
+
+ // Fire tooltip timer so tooltip becomes visible.
+ generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
+
+ generator_->PressKey(ui::VKEY_1, 0);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_FALSE(helper_->IsTooltipTimerRunning());
+ EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
+
+ // Moving the mouse inside |view1| should not change the state of the tooltip
+ // or the timers.
+ for (int i = 0; i < 49; i++) {
+ generator_->MoveMouseBy(1, 0);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_FALSE(helper_->IsTooltipTimerRunning());
+ EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
+ EXPECT_EQ(window,
+ GetRootWindow()->GetEventHandlerForPoint(
+ generator_->current_location()));
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(window, helper_->GetTooltipWindow());
+ }
+
+ // Now we move the mouse on to |view2|. It should re-start the tooltip timer.
+ generator_->MoveMouseBy(1, 0);
+ EXPECT_TRUE(helper_->IsTooltipTimerRunning());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(window, helper_->GetTooltipWindow());
+}
+
+TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
+ view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1"));
+ EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+
+ TooltipTestView* view2 = PrepareSecondView();
+ view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 2"));
+
+ aura::Window* window = GetWindow();
+
+ // Fire tooltip timer so tooltip becomes visible.
+ generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
+
+ helper_->FireTooltipShownTimer();
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_FALSE(helper_->IsTooltipTimerRunning());
+ EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
+
+ // Moving the mouse inside |view1| should not change the state of the tooltip
+ // or the timers.
+ for (int i = 0; i < 49; ++i) {
+ generator_->MoveMouseBy(1, 0);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_FALSE(helper_->IsTooltipTimerRunning());
+ EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
+ EXPECT_EQ(window, GetRootWindow()->GetEventHandlerForPoint(
+ generator_->current_location()));
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(window, helper_->GetTooltipWindow());
+ }
+
+ // Now we move the mouse on to |view2|. It should re-start the tooltip timer.
+ generator_->MoveMouseBy(1, 0);
+ EXPECT_TRUE(helper_->IsTooltipTimerRunning());
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
+ string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
+ EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
+ EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
+ EXPECT_EQ(window, helper_->GetTooltipWindow());
+}
+
+} // namespace test
+} // namespace corewm
+} // namespace views
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 2c347e0..43cfdaa 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -242,6 +242,8 @@
'corewm/shadow_controller.h',
'corewm/shadow_types.cc',
'corewm/shadow_types.h',
+ 'corewm/tooltip_controller.cc',
+ 'corewm/tooltip_controller.h',
'corewm/visibility_controller.cc',
'corewm/visibility_controller.h',
'corewm/window_animations.cc',
@@ -440,6 +442,8 @@
'widget/aero_tooltip_manager.h',
'widget/child_window_message_processor.cc',
'widget/child_window_message_processor.h',
+ 'widget/tooltip_manager_win.cc',
+ 'widget/tooltip_manager_win.h',
],
'conditions': [
['OS=="mac"', {
@@ -551,6 +555,8 @@
'..',
],
'sources': [
+ 'corewm/tooltip_controller_test_helper.cc',
+ 'corewm/tooltip_controller_test_helper.h',
'test/capture_tracking_view.cc',
'test/capture_tracking_view.h',
'test/child_modal_window.cc',
@@ -572,6 +578,8 @@
],
}, { # use_aura==0
'sources!': [
+ 'corewm/tooltip_controller_test_helper.cc',
+ 'corewm/tooltip_controller_test_helper.h',
'test/child_modal_window.cc',
'test/child_modal_window.h',
],
@@ -660,6 +668,7 @@
'corewm/image_grid_unittest.cc',
'corewm/input_method_event_filter_unittest.cc',
'corewm/shadow_controller_unittest.cc',
+ 'corewm/tooltip_controller_unittest.cc',
'corewm/visibility_controller_unittest.cc',
'focus/focus_manager_test.h',
'focus/focus_manager_test.cc',
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 282e0e8..2203e27 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -18,6 +18,7 @@
#include "ui/views/corewm/compound_event_filter.h"
#include "ui/views/corewm/corewm_switches.h"
#include "ui/views/corewm/input_method_event_filter.h"
+#include "ui/views/corewm/tooltip_controller.h"
#include "ui/views/drag_utils.h"
#include "ui/views/ime/input_method.h"
#include "ui/views/ime/input_method_bridge.h"
@@ -25,6 +26,7 @@
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/native_widget_aura_window_observer.h"
#include "ui/views/widget/root_view.h"
+#include "ui/views/widget/tooltip_manager_aura.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/widget/widget_delegate.h"
@@ -150,6 +152,13 @@ void DesktopNativeWidgetAura::InitNativeWidget(
static_cast<internal::RootView*>(GetWidget()->GetRootView())));
aura::client::SetDragDropDelegate(window_, this);
+ tooltip_manager_.reset(new views::TooltipManagerAura(window_, GetWidget()));
+ tooltip_controller_.reset(
+ new corewm::TooltipController(gfx::SCREEN_TYPE_NATIVE));
+ aura::client::SetTooltipClient(root_window_.get(),
+ tooltip_controller_.get());
+ root_window_->AddPreTargetHandler(tooltip_controller_.get());
+
aura::client::SetActivationDelegate(window_, this);
}
@@ -213,7 +222,7 @@ void* DesktopNativeWidgetAura::GetNativeWindowProperty(const char* name) const {
}
TooltipManager* DesktopNativeWidgetAura::GetTooltipManager() const {
- return NULL;
+ return tooltip_manager_.get();
}
bool DesktopNativeWidgetAura::IsScreenReaderActive() const {
@@ -528,6 +537,12 @@ void DesktopNativeWidgetAura::OnDeviceScaleFactorChanged(
void DesktopNativeWidgetAura::OnWindowDestroying() {
// The DesktopRootWindowHost implementation sends OnNativeWidgetDestroying().
+ tooltip_manager_.reset();
+ if (tooltip_controller_.get()) {
+ root_window_->RemovePreTargetHandler(tooltip_controller_.get());
+ tooltip_controller_.reset();
+ aura::client::SetTooltipClient(root_window_.get(), NULL);
+ }
}
void DesktopNativeWidgetAura::OnWindowDestroyed() {
@@ -583,6 +598,8 @@ void DesktopNativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) {
void DesktopNativeWidgetAura::OnMouseEvent(ui::MouseEvent* event) {
DCHECK(window_->IsVisible());
native_widget_delegate_->OnMouseEvent(event);
+ if (tooltip_manager_.get())
+ tooltip_manager_->UpdateTooltip();
}
void DesktopNativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) {
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 0f4c3cf..87b262c 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -26,11 +26,13 @@ namespace views {
namespace corewm {
class CompoundEventFilter;
class InputMethodEventFilter;
+class TooltipController;
}
class DesktopRootWindowHost;
class DropHelper;
class NativeWidgetAuraWindowObserver;
+class TooltipManagerAura;
// TODO(erg): May also need to be a DragDropDelegate
class VIEWS_EXPORT DesktopNativeWidgetAura
@@ -230,6 +232,9 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
scoped_ptr<DropHelper> drop_helper_;
int last_drop_operation_;
+ scoped_ptr<corewm::TooltipController> tooltip_controller_;
+ scoped_ptr<TooltipManagerAura> tooltip_manager_;
+
// See comments in OnLostActive().
bool restore_focus_on_activate_;
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
index 98aa130..06acf0d 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
@@ -610,7 +610,6 @@ void DesktopRootWindowHostWin::HandleCreate() {
// 1. Window property association
// 2. MouseWheel.
- // 3. Tooltip Manager.
}
void DesktopRootWindowHostWin::HandleDestroying() {
diff --git a/ui/views/widget/desktop_aura/desktop_screen_position_client.cc b/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
index 73554df..19fcbed 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
@@ -48,7 +48,8 @@ void DesktopScreenPositionClient::SetBounds(
if (window->type() == aura::client::WINDOW_TYPE_CONTROL) {
window->SetBounds(gfx::Rect(origin, bounds.size()));
return;
- } else if (window->type() == aura::client::WINDOW_TYPE_POPUP) {
+ } else if (window->type() == aura::client::WINDOW_TYPE_POPUP ||
+ window->type() == aura::client::WINDOW_TYPE_TOOLTIP) {
// The caller expects windows we consider "embedded" to be placed in the
// screen coordinate system. So we need to offset the root window's
// position (which is in screen coordinates) from these bounds.
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index b1a2738..a2d1e1a 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -157,7 +157,7 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
DCHECK(GetWidget()->GetRootView());
#if !defined(OS_MACOSX)
if (params.type != Widget::InitParams::TYPE_TOOLTIP)
- tooltip_manager_.reset(new views::TooltipManagerAura(this));
+ tooltip_manager_.reset(new views::TooltipManagerAura(window_, GetWidget()));
#endif // !defined(OS_MACOSX)
drop_helper_.reset(new DropHelper(GetWidget()->GetRootView()));
@@ -743,7 +743,6 @@ void NativeWidgetAura::OnWindowDestroying() {
void NativeWidgetAura::OnWindowDestroyed() {
window_ = NULL;
- tooltip_manager_.reset();
delegate_->OnNativeWidgetDestroyed();
if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
delete this;
diff --git a/ui/views/widget/tooltip_manager_aura.cc b/ui/views/widget/tooltip_manager_aura.cc
index 2b76750..a1d4ca8 100644
--- a/ui/views/widget/tooltip_manager_aura.cc
+++ b/ui/views/widget/tooltip_manager_aura.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/views/widget/tooltip_manager_aura.h"
+
#include "base/logging.h"
#include "ui/aura/client/tooltip_client.h"
#include "ui/aura/root_window.h"
@@ -9,8 +11,7 @@
#include "ui/gfx/font.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
-#include "ui/views/widget/native_widget_aura.h"
-#include "ui/views/widget/tooltip_manager_aura.h"
+#include "ui/views/widget/widget.h"
namespace views {
@@ -38,25 +39,24 @@ int TooltipManager::GetMaxWidth(int x, int y, gfx::NativeView context) {
////////////////////////////////////////////////////////////////////////////////
// TooltipManagerAura public:
-TooltipManagerAura::TooltipManagerAura(NativeWidgetAura* native_widget_aura)
- : native_widget_aura_(native_widget_aura) {
- aura::client::SetTooltipText(native_widget_aura_->GetNativeView(),
- &tooltip_text_);
+TooltipManagerAura::TooltipManagerAura(aura::Window* window, Widget* widget)
+ : window_(window),
+ widget_(widget) {
+ aura::client::SetTooltipText(window_, &tooltip_text_);
}
TooltipManagerAura::~TooltipManagerAura() {
- aura::client::SetTooltipText(native_widget_aura_->GetNativeView(), NULL);
+ aura::client::SetTooltipText(window_, NULL);
}
////////////////////////////////////////////////////////////////////////////////
// TooltipManagerAura, TooltipManager implementation:
void TooltipManagerAura::UpdateTooltip() {
- aura::Window* window = native_widget_aura_->GetNativeView();
- aura::RootWindow* root_window = window->GetRootWindow();
+ aura::RootWindow* root_window = window_->GetRootWindow();
if (aura::client::GetTooltipClient(root_window)) {
gfx::Point view_point = root_window->GetLastMouseLocationInRoot();
- aura::Window::ConvertPointToTarget(root_window, window, &view_point);
+ aura::Window::ConvertPointToTarget(root_window, window_, &view_point);
View* view = GetViewUnderPoint(view_point);
if (view) {
View::ConvertPointFromWidget(view, &view_point);
@@ -65,16 +65,15 @@ void TooltipManagerAura::UpdateTooltip() {
} else {
tooltip_text_.clear();
}
- aura::client::GetTooltipClient(root_window)->UpdateTooltip(window);
+ aura::client::GetTooltipClient(root_window)->UpdateTooltip(window_);
}
}
void TooltipManagerAura::TooltipTextChanged(View* view) {
- aura::Window* window = native_widget_aura_->GetNativeView();
- aura::RootWindow* root_window = window->GetRootWindow();
+ aura::RootWindow* root_window = window_->GetRootWindow();
if (aura::client::GetTooltipClient(root_window)) {
gfx::Point view_point = root_window->GetLastMouseLocationInRoot();
- aura::Window::ConvertPointToTarget(root_window, window, &view_point);
+ aura::Window::ConvertPointToTarget(root_window, window_, &view_point);
View* target = GetViewUnderPoint(view_point);
if (target != view)
return;
@@ -85,7 +84,7 @@ void TooltipManagerAura::TooltipTextChanged(View* view) {
} else {
tooltip_text_.clear();
}
- aura::client::GetTooltipClient(root_window)->UpdateTooltip(window);
+ aura::client::GetTooltipClient(root_window)->UpdateTooltip(window_);
}
}
@@ -98,8 +97,7 @@ void TooltipManagerAura::HideKeyboardTooltip() {
}
View* TooltipManagerAura::GetViewUnderPoint(const gfx::Point& point) {
- View* root_view = native_widget_aura_->GetWidget()->GetRootView();
- return root_view->GetEventHandlerForPoint(point);
+ return widget_->GetRootView()->GetEventHandlerForPoint(point);
}
} // namespace views.
diff --git a/ui/views/widget/tooltip_manager_aura.h b/ui/views/widget/tooltip_manager_aura.h
index 9e10917..6158820 100644
--- a/ui/views/widget/tooltip_manager_aura.h
+++ b/ui/views/widget/tooltip_manager_aura.h
@@ -10,15 +10,18 @@
#include "ui/gfx/point.h"
#include "ui/views/widget/tooltip_manager.h"
+namespace aura {
+class Window;
+}
+
namespace views {
-class NativeWidgetAura;
-class View;
+class Widget;
// TooltipManager implementation for Aura.
class TooltipManagerAura : public TooltipManager {
public:
- explicit TooltipManagerAura(NativeWidgetAura* native_widget_aura);
+ TooltipManagerAura(aura::Window* window, Widget* widget);
virtual ~TooltipManagerAura();
// TooltipManager.
@@ -30,7 +33,8 @@ class TooltipManagerAura : public TooltipManager {
private:
View* GetViewUnderPoint(const gfx::Point& point);
- NativeWidgetAura* native_widget_aura_;
+ aura::Window* window_;
+ Widget* widget_;
string16 tooltip_text_;
DISALLOW_COPY_AND_ASSIGN(TooltipManagerAura);