OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "views/widget/tooltip_manager_win.h" | 5 #include "views/widget/tooltip_manager_win.h" |
6 | 6 |
7 #include <windowsx.h> | 7 #include <windowsx.h> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "app/gfx/text_elider.h" | 10 #include "app/gfx/font.h" |
11 #include "app/l10n_util.h" | 11 #include "app/l10n_util.h" |
12 #include "app/l10n_util_win.h" | 12 #include "app/l10n_util_win.h" |
13 #include "app/win_util.h" | 13 #include "app/win_util.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
16 #include "views/view.h" | 16 #include "views/view.h" |
17 #include "views/widget/root_view.h" | 17 #include "views/widget/root_view.h" |
18 #include "views/widget/widget.h" | 18 #include "views/widget/widget.h" |
19 | 19 |
20 namespace views { | 20 namespace views { |
21 | 21 |
22 static int tooltip_height_ = 0; | 22 static int tooltip_height_ = 0; |
23 | 23 |
24 // Default timeout for the tooltip displayed using keyboard. | 24 // Default timeout for the tooltip displayed using keyboard. |
25 // Timeout is mentioned in milliseconds. | 25 // Timeout is mentioned in milliseconds. |
26 static const int kDefaultTimeout = 4000; | 26 static const int kDefaultTimeout = 4000; |
27 | 27 |
28 // Maximum number of lines we allow in the tooltip. | |
29 static const int kMaxLines = 6; | |
30 | |
31 // Maximum number of characters we allow in a tooltip. | |
32 static const int kMaxTooltipLength = 1024; | |
33 | |
34 // Breaks |text| along line boundaries, placing each line of text into lines. | |
35 static void SplitTooltipString(const std::wstring& text, | |
36 std::vector<std::wstring>* lines) { | |
37 size_t index = 0; | |
38 size_t next_index; | |
39 while ((next_index = text.find(TooltipManagerWin::GetLineSeparator(), index)) | |
40 != std::wstring::npos && lines->size() < kMaxLines) { | |
41 lines->push_back(text.substr(index, next_index - index)); | |
42 index = next_index + TooltipManagerWin::GetLineSeparator().size(); | |
43 } | |
44 if (next_index != text.size() && lines->size() < kMaxLines) | |
45 lines->push_back(text.substr(index, text.size() - index)); | |
46 } | |
47 | |
48 // static | 28 // static |
49 int TooltipManager::GetTooltipHeight() { | 29 int TooltipManager::GetTooltipHeight() { |
50 DCHECK(tooltip_height_ > 0); | 30 DCHECK(tooltip_height_ > 0); |
51 return tooltip_height_; | 31 return tooltip_height_; |
52 } | 32 } |
53 | 33 |
54 static gfx::Font DetermineDefaultFont() { | 34 static gfx::Font DetermineDefaultFont() { |
55 HWND window = CreateWindowEx( | 35 HWND window = CreateWindowEx( |
56 WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(), | 36 WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(), |
57 TOOLTIPS_CLASS, NULL, 0 , 0, 0, 0, 0, NULL, NULL, NULL, NULL); | 37 TOOLTIPS_CLASS, NULL, 0 , 0, 0, 0, 0, NULL, NULL, NULL, NULL); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 tooltip_text_.clear(); | 154 tooltip_text_.clear(); |
175 // Mouse is over a View, ask the View for it's tooltip. | 155 // Mouse is over a View, ask the View for it's tooltip. |
176 gfx::Point view_loc(last_mouse_x_, last_mouse_y_); | 156 gfx::Point view_loc(last_mouse_x_, last_mouse_y_); |
177 View::ConvertPointToView(widget_->GetRootView(), | 157 View::ConvertPointToView(widget_->GetRootView(), |
178 last_tooltip_view_, &view_loc); | 158 last_tooltip_view_, &view_loc); |
179 if (last_tooltip_view_->GetTooltipText(view_loc.x(), view_loc.y(), | 159 if (last_tooltip_view_->GetTooltipText(view_loc.x(), view_loc.y(), |
180 &tooltip_text_) && | 160 &tooltip_text_) && |
181 !tooltip_text_.empty()) { | 161 !tooltip_text_.empty()) { |
182 // View has a valid tip, copy it into TOOLTIPINFO. | 162 // View has a valid tip, copy it into TOOLTIPINFO. |
183 clipped_text_ = tooltip_text_; | 163 clipped_text_ = tooltip_text_; |
| 164 gfx::Point screen_loc(last_mouse_x_, last_mouse_y_); |
| 165 View::ConvertPointToScreen(widget_->GetRootView(), &screen_loc); |
184 TrimTooltipToFit(&clipped_text_, &tooltip_width_, &line_count_, | 166 TrimTooltipToFit(&clipped_text_, &tooltip_width_, &line_count_, |
185 last_mouse_x_, last_mouse_y_, tooltip_hwnd_); | 167 screen_loc.x(), screen_loc.y()); |
186 // Adjust the clipped tooltip text for locale direction. | 168 // Adjust the clipped tooltip text for locale direction. |
187 l10n_util::AdjustStringForLocaleDirection(clipped_text_, | 169 l10n_util::AdjustStringForLocaleDirection(clipped_text_, |
188 &clipped_text_); | 170 &clipped_text_); |
189 tooltip_info->lpszText = const_cast<WCHAR*>(clipped_text_.c_str()); | 171 tooltip_info->lpszText = const_cast<WCHAR*>(clipped_text_.c_str()); |
190 } else { | 172 } else { |
191 tooltip_text_.clear(); | 173 tooltip_text_.clear(); |
192 } | 174 } |
193 } | 175 } |
194 *handled = true; | 176 *handled = true; |
195 return 0; | 177 return 0; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 // Tooltip is using the system font. Use gfx::Font, which should pick | 254 // Tooltip is using the system font. Use gfx::Font, which should pick |
273 // up the system font. | 255 // up the system font. |
274 height = gfx::Font().height(); | 256 height = gfx::Font().height(); |
275 } | 257 } |
276 // Get the margins from the tooltip | 258 // Get the margins from the tooltip |
277 RECT tooltip_margin; | 259 RECT tooltip_margin; |
278 SendMessage(tooltip_hwnd_, TTM_GETMARGIN, 0, (LPARAM)&tooltip_margin); | 260 SendMessage(tooltip_hwnd_, TTM_GETMARGIN, 0, (LPARAM)&tooltip_margin); |
279 return height + tooltip_margin.top + tooltip_margin.bottom; | 261 return height + tooltip_margin.top + tooltip_margin.bottom; |
280 } | 262 } |
281 | 263 |
282 void TooltipManagerWin::TrimTooltipToFit(std::wstring* text, | |
283 int* max_width, | |
284 int* line_count, | |
285 int position_x, | |
286 int position_y, | |
287 HWND window) { | |
288 *max_width = 0; | |
289 *line_count = 0; | |
290 | |
291 // Clamp the tooltip length to kMaxTooltipLength so that we don't | |
292 // accidentally DOS the user with a mega tooltip (since Windows doesn't seem | |
293 // to do this itself). | |
294 if (text->length() > kMaxTooltipLength) | |
295 *text = text->substr(0, kMaxTooltipLength); | |
296 | |
297 // Determine the available width for the tooltip. | |
298 gfx::Point screen_loc(position_x, position_y); | |
299 View::ConvertPointToScreen(widget_->GetRootView(), &screen_loc); | |
300 gfx::Rect monitor_bounds = | |
301 win_util::GetMonitorBoundsForRect(gfx::Rect(screen_loc.x(), | |
302 screen_loc.y(), | |
303 0, 0)); | |
304 RECT tooltip_margin; | |
305 SendMessage(window, TTM_GETMARGIN, 0, (LPARAM)&tooltip_margin); | |
306 const int available_width = monitor_bounds.width() - tooltip_margin.left - | |
307 tooltip_margin.right; | |
308 if (available_width <= 0) | |
309 return; | |
310 | |
311 // Split the string. | |
312 std::vector<std::wstring> lines; | |
313 SplitTooltipString(*text, &lines); | |
314 *line_count = static_cast<int>(lines.size()); | |
315 | |
316 // Format each line to fit. | |
317 gfx::Font font = GetDefaultFont(); | |
318 std::wstring result; | |
319 for (std::vector<std::wstring>::iterator i = lines.begin(); i != lines.end(); | |
320 ++i) { | |
321 std::wstring elided_text = gfx::ElideText(*i, font, available_width); | |
322 *max_width = std::max(*max_width, font.GetStringWidth(elided_text)); | |
323 if (i == lines.begin() && i + 1 == lines.end()) { | |
324 *text = elided_text; | |
325 return; | |
326 } | |
327 if (!result.empty()) | |
328 result.append(GetLineSeparator()); | |
329 result.append(elided_text); | |
330 } | |
331 *text = result; | |
332 } | |
333 | |
334 void TooltipManagerWin::UpdateTooltip(int x, int y) { | 264 void TooltipManagerWin::UpdateTooltip(int x, int y) { |
335 RootView* root_view = widget_->GetRootView(); | 265 RootView* root_view = widget_->GetRootView(); |
336 View* view = root_view->GetViewForPoint(gfx::Point(x, y)); | 266 View* view = root_view->GetViewForPoint(gfx::Point(x, y)); |
337 if (view != last_tooltip_view_) { | 267 if (view != last_tooltip_view_) { |
338 // NOTE: This *must* be sent regardless of the visibility of the tooltip. | 268 // NOTE: This *must* be sent regardless of the visibility of the tooltip. |
339 // It triggers Windows to ask for the tooltip again. | 269 // It triggers Windows to ask for the tooltip again. |
340 SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); | 270 SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
341 last_tooltip_view_ = view; | 271 last_tooltip_view_ = view; |
342 } else if (last_tooltip_view_ != NULL) { | 272 } else if (last_tooltip_view_ != NULL) { |
343 // Tooltip is showing, and mouse is over the same view. See if the tooltip | 273 // Tooltip is showing, and mouse is over the same view. See if the tooltip |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); | 320 SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
391 tooltip_text_.clear(); | 321 tooltip_text_.clear(); |
392 } | 322 } |
393 HideKeyboardTooltip(); | 323 HideKeyboardTooltip(); |
394 std::wstring tooltip_text; | 324 std::wstring tooltip_text; |
395 if (!focused_view->GetTooltipText(0, 0, &tooltip_text)) | 325 if (!focused_view->GetTooltipText(0, 0, &tooltip_text)) |
396 return; | 326 return; |
397 gfx::Rect focused_bounds = focused_view->bounds(); | 327 gfx::Rect focused_bounds = focused_view->bounds(); |
398 gfx::Point screen_point; | 328 gfx::Point screen_point; |
399 focused_view->ConvertPointToScreen(focused_view, &screen_point); | 329 focused_view->ConvertPointToScreen(focused_view, &screen_point); |
400 gfx::Point relative_point_coordinates; | |
401 focused_view->ConvertPointToWidget(focused_view, &relative_point_coordinates); | |
402 keyboard_tooltip_hwnd_ = CreateWindowEx( | 330 keyboard_tooltip_hwnd_ = CreateWindowEx( |
403 WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(), | 331 WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(), |
404 TOOLTIPS_CLASS, NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); | 332 TOOLTIPS_CLASS, NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); |
405 SendMessage(keyboard_tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, | 333 SendMessage(keyboard_tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, |
406 std::numeric_limits<short>::max()); | 334 std::numeric_limits<short>::max()); |
407 int tooltip_width; | 335 int tooltip_width; |
408 int line_count; | 336 int line_count; |
409 TrimTooltipToFit(&tooltip_text, &tooltip_width, &line_count, | 337 TrimTooltipToFit(&tooltip_text, &tooltip_width, &line_count, |
410 relative_point_coordinates.x(), | 338 screen_point.x(), screen_point.y()); |
411 relative_point_coordinates.y(), keyboard_tooltip_hwnd_); | |
412 TOOLINFO keyboard_toolinfo; | 339 TOOLINFO keyboard_toolinfo; |
413 memset(&keyboard_toolinfo, 0, sizeof(keyboard_toolinfo)); | 340 memset(&keyboard_toolinfo, 0, sizeof(keyboard_toolinfo)); |
414 keyboard_toolinfo.cbSize = sizeof(keyboard_toolinfo); | 341 keyboard_toolinfo.cbSize = sizeof(keyboard_toolinfo); |
415 keyboard_toolinfo.hwnd = GetParent(); | 342 keyboard_toolinfo.hwnd = GetParent(); |
416 keyboard_toolinfo.uFlags = TTF_TRACK | TTF_TRANSPARENT | TTF_IDISHWND ; | 343 keyboard_toolinfo.uFlags = TTF_TRACK | TTF_TRANSPARENT | TTF_IDISHWND ; |
417 keyboard_toolinfo.lpszText = const_cast<WCHAR*>(tooltip_text.c_str()); | 344 keyboard_toolinfo.lpszText = const_cast<WCHAR*>(tooltip_text.c_str()); |
418 SendMessage(keyboard_tooltip_hwnd_, TTM_ADDTOOL, 0, | 345 SendMessage(keyboard_tooltip_hwnd_, TTM_ADDTOOL, 0, |
419 reinterpret_cast<LPARAM>(&keyboard_toolinfo)); | 346 reinterpret_cast<LPARAM>(&keyboard_toolinfo)); |
420 SendMessage(keyboard_tooltip_hwnd_, TTM_TRACKACTIVATE, TRUE, | 347 SendMessage(keyboard_tooltip_hwnd_, TTM_TRACKACTIVATE, TRUE, |
421 reinterpret_cast<LPARAM>(&keyboard_toolinfo)); | 348 reinterpret_cast<LPARAM>(&keyboard_toolinfo)); |
(...skipping 23 matching lines...) Expand all Loading... |
445 keyboard_tooltip_hwnd_ = NULL; | 372 keyboard_tooltip_hwnd_ = NULL; |
446 } | 373 } |
447 } | 374 } |
448 | 375 |
449 void TooltipManagerWin::DestroyKeyboardTooltipWindow(HWND window_to_destroy) { | 376 void TooltipManagerWin::DestroyKeyboardTooltipWindow(HWND window_to_destroy) { |
450 if (keyboard_tooltip_hwnd_ == window_to_destroy) | 377 if (keyboard_tooltip_hwnd_ == window_to_destroy) |
451 HideKeyboardTooltip(); | 378 HideKeyboardTooltip(); |
452 } | 379 } |
453 | 380 |
454 } // namespace views | 381 } // namespace views |
OLD | NEW |