1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/corewm/tooltip_win.h"
9 #include "base/debug/stack_trace.h"
10 #include "base/i18n/rtl.h"
11 #include "base/logging.h"
12 #include "ui/base/l10n/l10n_util_win.h"
13 #include "ui/gfx/rect.h"
14 #include "ui/gfx/screen.h"
15 #include "ui/gfx/win/dpi.h"
16 #include "ui/views/corewm/cursor_height_provider_win.h"
21 TooltipWin::TooltipWin(HWND parent
)
22 : parent_hwnd_(parent
),
25 memset(&toolinfo_
, 0, sizeof(toolinfo_
));
26 toolinfo_
.cbSize
= sizeof(toolinfo_
);
27 toolinfo_
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
28 toolinfo_
.uId
= reinterpret_cast<UINT_PTR
>(parent_hwnd_
);
29 toolinfo_
.hwnd
= parent_hwnd_
;
30 toolinfo_
.lpszText
= NULL
;
31 toolinfo_
.lpReserved
= NULL
;
32 SetRectEmpty(&toolinfo_
.rect
);
35 TooltipWin::~TooltipWin() {
37 DestroyWindow(tooltip_hwnd_
);
40 bool TooltipWin::HandleNotify(int w_param
, NMHDR
* l_param
, LRESULT
* l_result
) {
41 if (tooltip_hwnd_
== NULL
)
44 switch (l_param
->code
) {
59 bool TooltipWin::EnsureTooltipWindow() {
63 tooltip_hwnd_
= CreateWindowEx(
64 WS_EX_TRANSPARENT
| l10n_util::GetExtendedTooltipStyles(),
65 TOOLTIPS_CLASS
, NULL
, TTS_NOPREFIX
| WS_POPUP
, 0, 0, 0, 0,
66 parent_hwnd_
, NULL
, NULL
, NULL
);
68 PLOG(WARNING
) << "tooltip creation failed, disabling tooltips";
72 l10n_util::AdjustUIFontForWindow(tooltip_hwnd_
);
74 SendMessage(tooltip_hwnd_
, TTM_ADDTOOL
, 0,
75 reinterpret_cast<LPARAM
>(&toolinfo_
));
79 void TooltipWin::PositionTooltip() {
80 // This code only runs for non-metro, so GetNativeScreen() is fine.
81 gfx::Point screen_point
= gfx::win::DIPToScreenPoint(location_
);
82 const int cursoroffset
= GetCurrentCursorVisibleHeight();
83 screen_point
.Offset(0, cursoroffset
);
85 DWORD tooltip_size
= SendMessage(tooltip_hwnd_
, TTM_GETBUBBLESIZE
, 0,
86 reinterpret_cast<LPARAM
>(&toolinfo_
));
87 const gfx::Size
size(LOWORD(tooltip_size
), HIWORD(tooltip_size
));
89 const gfx::Display
display(
90 gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point
));
92 gfx::Rect
tooltip_bounds(screen_point
, size
);
93 tooltip_bounds
.AdjustToFit(gfx::win::DIPToScreenRect(display
.work_area()));
94 SetWindowPos(tooltip_hwnd_
, NULL
, tooltip_bounds
.x(), tooltip_bounds
.y(), 0,
95 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
98 void TooltipWin::SetText(aura::Window
* window
,
99 const base::string16
& tooltip_text
,
100 const gfx::Point
& location
) {
101 if (!EnsureTooltipWindow())
104 // See comment in header for details on why |location_| is needed.
105 location_
= location
;
107 // Without this we get a flicker of the tooltip appearing at 0x0. Not sure
109 SetWindowPos(tooltip_hwnd_
, NULL
, 0, 0, 0, 0,
110 SWP_HIDEWINDOW
| SWP_NOACTIVATE
| SWP_NOMOVE
|
111 SWP_NOREPOSITION
| SWP_NOSIZE
| SWP_NOZORDER
);
113 base::string16
adjusted_text(tooltip_text
);
114 base::i18n::AdjustStringForLocaleDirection(&adjusted_text
);
115 toolinfo_
.lpszText
= const_cast<WCHAR
*>(adjusted_text
.c_str());
116 SendMessage(tooltip_hwnd_
, TTM_SETTOOLINFO
, 0,
117 reinterpret_cast<LPARAM
>(&toolinfo_
));
119 // This code only runs for non-metro, so GetNativeScreen() is fine.
120 const gfx::Point screen_point
= gfx::win::DIPToScreenPoint(location_
);
121 gfx::Display
display(
122 gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point
));
123 const gfx::Rect monitor_bounds
= display
.bounds();
124 int max_width
= (monitor_bounds
.width() + 1) / 2;
125 SendMessage(tooltip_hwnd_
, TTM_SETMAXTIPWIDTH
, 0, max_width
);
128 void TooltipWin::Show() {
129 if (!EnsureTooltipWindow())
132 SendMessage(tooltip_hwnd_
, TTM_TRACKACTIVATE
,
133 TRUE
, reinterpret_cast<LPARAM
>(&toolinfo_
));
134 SetWindowPos(tooltip_hwnd_
, HWND_TOPMOST
, 0, 0, 0, 0,
135 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
);
138 void TooltipWin::Hide() {
142 SendMessage(tooltip_hwnd_
, TTM_TRACKACTIVATE
, FALSE
,
143 reinterpret_cast<LPARAM
>(&toolinfo_
));
146 bool TooltipWin::IsVisible() {
150 } // namespace corewm