Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/corewm/tooltip_controller.h" | 5 #include "ui/views/corewm/tooltip_controller.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 15 #include "ui/aura/client/capture_client.h" | 15 #include "ui/aura/client/capture_client.h" |
| 16 #include "ui/aura/client/cursor_client.h" | 16 #include "ui/aura/client/cursor_client.h" |
| 17 #include "ui/aura/client/drag_drop_client.h" | 17 #include "ui/aura/client/drag_drop_client.h" |
| 18 #include "ui/aura/client/screen_position_client.h" | 18 #include "ui/aura/client/screen_position_client.h" |
| 19 #include "ui/aura/env.h" | 19 #include "ui/aura/env.h" |
| 20 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
| 21 #include "ui/display/screen.h" | 21 #include "ui/display/screen.h" |
| 22 #include "ui/events/event.h" | 22 #include "ui/events/event.h" |
| 23 #include "ui/gfx/font.h" | 23 #include "ui/gfx/font.h" |
| 24 #include "ui/gfx/geometry/rect.h" | 24 #include "ui/gfx/geometry/rect.h" |
| 25 #include "ui/gfx/text_elider.h" | 25 #include "ui/gfx/text_elider.h" |
| 26 #include "ui/views/corewm/tooltip.h" | 26 #include "ui/views/corewm/tooltip.h" |
| 27 #include "ui/views/widget/tooltip_manager.h" | 27 #include "ui/views/widget/tooltip_manager.h" |
| 28 #include "ui/wm/public/tooltip_client.h" | |
| 28 | 29 |
| 29 namespace views { | 30 namespace views { |
| 30 namespace corewm { | 31 namespace corewm { |
| 31 namespace { | 32 namespace { |
| 32 | 33 |
| 33 const int kTooltipTimeoutMs = 500; | |
| 34 const int kDefaultTooltipShownTimeoutMs = 10000; | 34 const int kDefaultTooltipShownTimeoutMs = 10000; |
| 35 #if defined(OS_WIN) | 35 #if defined(OS_WIN) |
| 36 // Drawing a long word in tooltip is very slow on Windows. crbug.com/513693 | 36 // Drawing a long word in tooltip is very slow on Windows. crbug.com/513693 |
| 37 const size_t kMaxTooltipLength = 1024; | 37 const size_t kMaxTooltipLength = 1024; |
| 38 #else | 38 #else |
| 39 const size_t kMaxTooltipLength = 2048; | 39 const size_t kMaxTooltipLength = 2048; |
| 40 #endif | 40 #endif |
| 41 | 41 |
| 42 // Returns true if |target| is a valid window to get the tooltip from. | 42 // Returns true if |target| is a valid window to get the tooltip from. |
| 43 // |event_target| is the original target from the event and |target| the window | 43 // |event_target| is the original target from the event and |target| the window |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 } // namespace | 122 } // namespace |
| 123 | 123 |
| 124 //////////////////////////////////////////////////////////////////////////////// | 124 //////////////////////////////////////////////////////////////////////////////// |
| 125 // TooltipController public: | 125 // TooltipController public: |
| 126 | 126 |
| 127 TooltipController::TooltipController(std::unique_ptr<Tooltip> tooltip) | 127 TooltipController::TooltipController(std::unique_ptr<Tooltip> tooltip) |
| 128 : tooltip_window_(NULL), | 128 : tooltip_window_(NULL), |
| 129 tooltip_id_(NULL), | 129 tooltip_id_(NULL), |
| 130 tooltip_window_at_mouse_press_(NULL), | 130 tooltip_window_at_mouse_press_(NULL), |
| 131 tooltip_(std::move(tooltip)), | 131 tooltip_(std::move(tooltip)), |
| 132 tooltips_enabled_(true) { | 132 tooltips_enabled_(true) {} |
| 133 tooltip_timer_.Start(FROM_HERE, | |
| 134 base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs), | |
| 135 this, &TooltipController::TooltipTimerFired); | |
| 136 } | |
| 137 | 133 |
| 138 TooltipController::~TooltipController() { | 134 TooltipController::~TooltipController() { |
| 139 if (tooltip_window_) | 135 if (tooltip_window_) |
| 140 tooltip_window_->RemoveObserver(this); | 136 tooltip_window_->RemoveObserver(this); |
| 141 } | 137 } |
| 142 | 138 |
| 143 int TooltipController::GetMaxWidth(const gfx::Point& location) const { | 139 int TooltipController::GetMaxWidth(const gfx::Point& location) const { |
| 144 return tooltip_->GetMaxWidth(location); | 140 return tooltip_->GetMaxWidth(location); |
| 145 } | 141 } |
| 146 | 142 |
| 147 void TooltipController::UpdateTooltip(aura::Window* target) { | 143 void TooltipController::UpdateTooltip(aura::Window* target) { |
| 148 // If tooltip is visible, we may want to hide it. If it is not, we are ok. | 144 // If tooltip is visible, we may want to hide it. If it is not, we are ok. |
| 149 if (tooltip_window_ == target && tooltip_->IsVisible()) | 145 if (tooltip_window_ == target && tooltip_->IsVisible()) |
| 150 UpdateIfRequired(); | 146 UpdateIfRequired(); |
| 151 | 147 |
| 152 // Reset |tooltip_window_at_mouse_press_| if the moving within the same window | 148 // Reset |tooltip_window_at_mouse_press_| if the moving within the same window |
| 153 // but over a region that has different tooltip text. By resetting | 149 // but over a region that has different tooltip text. |
| 154 // |tooltip_window_at_mouse_press_| we ensure the next time the timer fires | |
| 155 // we'll requery for the tooltip text. | |
| 156 // This handles the case of clicking on a view, moving within the same window | 150 // This handles the case of clicking on a view, moving within the same window |
| 157 // but over a different view, than back to the original. | 151 // but over a different view, than back to the original. |
| 158 if (tooltip_window_at_mouse_press_ && | 152 if (tooltip_window_at_mouse_press_ && |
| 159 target == tooltip_window_at_mouse_press_ && | 153 target == tooltip_window_at_mouse_press_ && |
| 160 aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) { | 154 aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) { |
| 161 tooltip_window_at_mouse_press_ = NULL; | 155 tooltip_window_at_mouse_press_ = NULL; |
| 162 } | 156 } |
| 163 | |
| 164 // If we had stopped the tooltip timer for some reason, we must restart it if | |
| 165 // there is a change in the tooltip. | |
| 166 if (!tooltip_timer_.IsRunning()) { | |
| 167 if (tooltip_window_ != target || (tooltip_window_ && | |
| 168 tooltip_text_ != aura::client::GetTooltipText(tooltip_window_))) { | |
| 169 tooltip_timer_.Start(FROM_HERE, | |
| 170 base::TimeDelta::FromMilliseconds(kTooltipTimeoutMs), | |
| 171 this, &TooltipController::TooltipTimerFired); | |
| 172 } | |
| 173 } | |
| 174 } | 157 } |
| 175 | 158 |
| 176 void TooltipController::SetTooltipShownTimeout(aura::Window* target, | 159 void TooltipController::SetTooltipShownTimeout(aura::Window* target, |
| 177 int timeout_in_ms) { | 160 int timeout_in_ms) { |
| 178 tooltip_shown_timeout_map_[target] = timeout_in_ms; | 161 tooltip_shown_timeout_map_[target] = timeout_in_ms; |
| 179 } | 162 } |
| 180 | 163 |
| 181 void TooltipController::SetTooltipsEnabled(bool enable) { | 164 void TooltipController::SetTooltipsEnabled(bool enable) { |
| 182 if (tooltips_enabled_ == enable) | 165 if (tooltips_enabled_ == enable) |
| 183 return; | 166 return; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 204 curr_mouse_loc_ = event->location(); | 187 curr_mouse_loc_ = event->location(); |
| 205 aura::Window* target = NULL; | 188 aura::Window* target = NULL; |
| 206 // Avoid a call to display::Screen::GetWindowAtScreenPoint() since it can | 189 // Avoid a call to display::Screen::GetWindowAtScreenPoint() since it can |
| 207 // be very expensive on X11 in cases when the tooltip is hidden anyway. | 190 // be very expensive on X11 in cases when the tooltip is hidden anyway. |
| 208 if (tooltips_enabled_ && | 191 if (tooltips_enabled_ && |
| 209 !aura::Env::GetInstance()->IsMouseButtonDown() && | 192 !aura::Env::GetInstance()->IsMouseButtonDown() && |
| 210 !IsDragDropInProgress()) { | 193 !IsDragDropInProgress()) { |
| 211 target = GetTooltipTarget(*event, &curr_mouse_loc_); | 194 target = GetTooltipTarget(*event, &curr_mouse_loc_); |
| 212 } | 195 } |
| 213 SetTooltipWindow(target); | 196 SetTooltipWindow(target); |
| 214 if (tooltip_timer_.IsRunning()) | |
| 215 tooltip_timer_.Reset(); | |
| 216 | 197 |
| 217 if (tooltip_->IsVisible()) | 198 if (tooltip_->IsVisible() || |
| 199 (tooltip_window_ && | |
|
sky
2017/01/12 20:15:18
How come you are adding this condition?
chengx
2017/01/13 01:17:51
Because before this change, OnMouseEvent() only tr
| |
| 200 tooltip_text_ != aura::client::GetTooltipText(tooltip_window_))) | |
| 218 UpdateIfRequired(); | 201 UpdateIfRequired(); |
| 219 break; | 202 break; |
| 220 } | 203 } |
| 221 case ui::ET_MOUSE_PRESSED: | 204 case ui::ET_MOUSE_PRESSED: |
| 222 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) { | 205 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) { |
| 223 aura::Window* target = static_cast<aura::Window*>(event->target()); | 206 aura::Window* target = static_cast<aura::Window*>(event->target()); |
| 224 // We don't get a release for non-client areas. | 207 // We don't get a release for non-client areas. |
| 225 tooltip_window_at_mouse_press_ = target; | 208 tooltip_window_at_mouse_press_ = target; |
| 226 if (target) | 209 if (target) |
| 227 tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target); | 210 tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target); |
| 228 } | 211 } |
| 229 tooltip_->Hide(); | 212 tooltip_->Hide(); |
| 230 break; | 213 break; |
| 231 case ui::ET_MOUSEWHEEL: | 214 case ui::ET_MOUSEWHEEL: |
| 232 // Hide the tooltip for click, release, drag, wheel events. | 215 // Hide the tooltip for click, release, drag, wheel events. |
| 233 if (tooltip_->IsVisible()) | 216 if (tooltip_->IsVisible()) |
| 234 tooltip_->Hide(); | 217 tooltip_->Hide(); |
| 235 | |
| 236 // Don't reshow the tooltip during scroll. | |
| 237 if (tooltip_timer_.IsRunning()) | |
| 238 tooltip_timer_.Reset(); | |
| 239 break; | 218 break; |
| 240 default: | 219 default: |
| 241 break; | 220 break; |
| 242 } | 221 } |
| 243 } | 222 } |
| 244 | 223 |
| 245 void TooltipController::OnTouchEvent(ui::TouchEvent* event) { | 224 void TooltipController::OnTouchEvent(ui::TouchEvent* event) { |
| 246 // TODO(varunjain): need to properly implement tooltips for | 225 // TODO(varunjain): need to properly implement tooltips for |
| 247 // touch events. | 226 // touch events. |
| 248 // Hide the tooltip for touch events. | 227 // Hide the tooltip for touch events. |
| 249 tooltip_->Hide(); | 228 tooltip_->Hide(); |
| 250 SetTooltipWindow(NULL); | 229 SetTooltipWindow(NULL); |
| 251 } | 230 } |
| 252 | 231 |
| 253 void TooltipController::OnCancelMode(ui::CancelModeEvent* event) { | 232 void TooltipController::OnCancelMode(ui::CancelModeEvent* event) { |
| 254 tooltip_->Hide(); | 233 tooltip_->Hide(); |
| 255 SetTooltipWindow(NULL); | 234 SetTooltipWindow(NULL); |
| 256 } | 235 } |
| 257 | 236 |
| 237 void TooltipController::OnCursorVisibilityChanged(bool is_visible) { | |
| 238 UpdateIfRequired(); | |
| 239 } | |
| 240 | |
| 258 void TooltipController::OnWindowDestroyed(aura::Window* window) { | 241 void TooltipController::OnWindowDestroyed(aura::Window* window) { |
| 259 if (tooltip_window_ == window) { | 242 if (tooltip_window_ == window) { |
| 260 tooltip_->Hide(); | 243 tooltip_->Hide(); |
| 261 tooltip_shown_timeout_map_.erase(tooltip_window_); | 244 tooltip_shown_timeout_map_.erase(tooltip_window_); |
| 262 tooltip_window_ = NULL; | 245 tooltip_window_ = NULL; |
| 263 } | 246 } |
| 264 } | 247 } |
| 265 | 248 |
| 249 void TooltipController::OnWindowPropertyChanged(aura::Window* window, | |
| 250 const void* key, | |
| 251 intptr_t old) { | |
| 252 if ((key == aura::client::kTooltipIdKey || | |
| 253 key == aura::client::kTooltipTextKey) && | |
| 254 window && tooltip_window_ == window && | |
|
sky
2017/01/12 20:15:18
Why do you need to check window and tooltip_window
chengx
2017/01/13 01:17:51
You are right. I have removed those two checks.
| |
| 255 aura::client::GetTooltipText(window) != base::string16() && | |
| 256 (tooltip_text_ != aura::client::GetTooltipText(window) || | |
| 257 tooltip_id_ != aura::client::GetTooltipId(window))) | |
| 258 UpdateIfRequired(); | |
| 259 } | |
| 260 | |
| 266 //////////////////////////////////////////////////////////////////////////////// | 261 //////////////////////////////////////////////////////////////////////////////// |
| 267 // TooltipController private: | 262 // TooltipController private: |
| 268 | 263 |
| 269 void TooltipController::TooltipTimerFired() { | |
| 270 UpdateIfRequired(); | |
| 271 } | |
| 272 | |
| 273 void TooltipController::TooltipShownTimerFired() { | 264 void TooltipController::TooltipShownTimerFired() { |
| 274 tooltip_->Hide(); | 265 tooltip_->Hide(); |
| 275 | |
| 276 // Since the user presumably no longer needs the tooltip, we also stop the | |
| 277 // tooltip timer so that tooltip does not pop back up. We will restart this | |
| 278 // timer if the tooltip changes (see UpdateTooltip()). | |
| 279 tooltip_timer_.Stop(); | |
| 280 } | 266 } |
| 281 | 267 |
| 282 void TooltipController::UpdateIfRequired() { | 268 void TooltipController::UpdateIfRequired() { |
| 283 if (!tooltips_enabled_ || | 269 if (!tooltips_enabled_ || |
| 284 aura::Env::GetInstance()->IsMouseButtonDown() || | 270 aura::Env::GetInstance()->IsMouseButtonDown() || |
| 285 IsDragDropInProgress() || !IsCursorVisible()) { | 271 IsDragDropInProgress() || !IsCursorVisible()) { |
| 286 tooltip_->Hide(); | 272 tooltip_->Hide(); |
| 287 return; | 273 return; |
| 288 } | 274 } |
| 289 | 275 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 302 tooltip_window_at_mouse_press_ = NULL; | 288 tooltip_window_at_mouse_press_ = NULL; |
| 303 } | 289 } |
| 304 | 290 |
| 305 // If the uniqueness indicator is different from the previously encountered | 291 // If the uniqueness indicator is different from the previously encountered |
| 306 // one, we should force tooltip update | 292 // one, we should force tooltip update |
| 307 const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_); | 293 const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_); |
| 308 bool ids_differ = false; | 294 bool ids_differ = false; |
| 309 ids_differ = tooltip_id_ != tooltip_id; | 295 ids_differ = tooltip_id_ != tooltip_id; |
| 310 tooltip_id_ = tooltip_id; | 296 tooltip_id_ = tooltip_id; |
| 311 | 297 |
| 312 // We add the !tooltip_->IsVisible() below because when we come here from | |
| 313 // TooltipTimerFired(), the tooltip_text may not have changed but we still | |
| 314 // want to update the tooltip because the timer has fired. | |
| 315 // If we come here from UpdateTooltip(), we have already checked for tooltip | 298 // If we come here from UpdateTooltip(), we have already checked for tooltip |
| 316 // visibility and this check below will have no effect. | 299 // visibility and this check below will have no effect. |
| 317 if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) { | 300 if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) { |
| 318 tooltip_shown_timer_.Stop(); | 301 tooltip_shown_timer_.Stop(); |
| 319 tooltip_text_ = tooltip_text; | 302 tooltip_text_ = tooltip_text; |
| 320 base::string16 trimmed_text = | 303 base::string16 trimmed_text = |
| 321 gfx::TruncateString(tooltip_text_, kMaxTooltipLength, gfx::WORD_BREAK); | 304 gfx::TruncateString(tooltip_text_, kMaxTooltipLength, gfx::WORD_BREAK); |
| 322 // If the string consists entirely of whitespace, then don't both showing it | 305 // If the string consists entirely of whitespace, then don't both showing it |
| 323 // (an empty tooltip is useless). | 306 // (an empty tooltip is useless). |
| 324 base::string16 whitespace_removed_text; | 307 base::string16 whitespace_removed_text; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 return; | 361 return; |
| 379 if (tooltip_window_) | 362 if (tooltip_window_) |
| 380 tooltip_window_->RemoveObserver(this); | 363 tooltip_window_->RemoveObserver(this); |
| 381 tooltip_window_ = target; | 364 tooltip_window_ = target; |
| 382 if (tooltip_window_) | 365 if (tooltip_window_) |
| 383 tooltip_window_->AddObserver(this); | 366 tooltip_window_->AddObserver(this); |
| 384 } | 367 } |
| 385 | 368 |
| 386 } // namespace corewm | 369 } // namespace corewm |
| 387 } // namespace views | 370 } // namespace views |
| OLD | NEW |