| 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" | |
| 29 | 28 |
| 30 namespace views { | 29 namespace views { |
| 31 namespace corewm { | 30 namespace corewm { |
| 32 namespace { | 31 namespace { |
| 33 | 32 |
| 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 } |
| 133 | 137 |
| 134 TooltipController::~TooltipController() { | 138 TooltipController::~TooltipController() { |
| 135 if (tooltip_window_) | 139 if (tooltip_window_) |
| 136 tooltip_window_->RemoveObserver(this); | 140 tooltip_window_->RemoveObserver(this); |
| 137 } | 141 } |
| 138 | 142 |
| 139 int TooltipController::GetMaxWidth(const gfx::Point& location) const { | 143 int TooltipController::GetMaxWidth(const gfx::Point& location) const { |
| 140 return tooltip_->GetMaxWidth(location); | 144 return tooltip_->GetMaxWidth(location); |
| 141 } | 145 } |
| 142 | 146 |
| 143 void TooltipController::UpdateTooltip(aura::Window* target) { | 147 void TooltipController::UpdateTooltip(aura::Window* target) { |
| 144 // If tooltip is visible, we may want to hide it. If it is not, we are ok. | 148 // If tooltip is visible, we may want to hide it. If it is not, we are ok. |
| 145 if (tooltip_window_ == target && tooltip_->IsVisible()) | 149 if (tooltip_window_ == target && tooltip_->IsVisible()) |
| 146 UpdateIfRequired(); | 150 UpdateIfRequired(); |
| 147 | 151 |
| 148 // Reset |tooltip_window_at_mouse_press_| if the moving within the same window | 152 // Reset |tooltip_window_at_mouse_press_| if the moving within the same window |
| 149 // but over a region that has different tooltip text. | 153 // but over a region that has different tooltip text. By resetting |
| 154 // |tooltip_window_at_mouse_press_| we ensure the next time the timer fires |
| 155 // we'll requery for the tooltip text. |
| 150 // This handles the case of clicking on a view, moving within the same window | 156 // This handles the case of clicking on a view, moving within the same window |
| 151 // but over a different view, than back to the original. | 157 // but over a different view, than back to the original. |
| 152 if (tooltip_window_at_mouse_press_ && | 158 if (tooltip_window_at_mouse_press_ && |
| 153 target == tooltip_window_at_mouse_press_ && | 159 target == tooltip_window_at_mouse_press_ && |
| 154 aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) { | 160 aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) { |
| 155 tooltip_window_at_mouse_press_ = NULL; | 161 tooltip_window_at_mouse_press_ = NULL; |
| 156 } | 162 } |
| 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 } |
| 157 } | 174 } |
| 158 | 175 |
| 159 void TooltipController::SetTooltipShownTimeout(aura::Window* target, | 176 void TooltipController::SetTooltipShownTimeout(aura::Window* target, |
| 160 int timeout_in_ms) { | 177 int timeout_in_ms) { |
| 161 tooltip_shown_timeout_map_[target] = timeout_in_ms; | 178 tooltip_shown_timeout_map_[target] = timeout_in_ms; |
| 162 } | 179 } |
| 163 | 180 |
| 164 void TooltipController::SetTooltipsEnabled(bool enable) { | 181 void TooltipController::SetTooltipsEnabled(bool enable) { |
| 165 if (tooltips_enabled_ == enable) | 182 if (tooltips_enabled_ == enable) |
| 166 return; | 183 return; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 187 curr_mouse_loc_ = event->location(); | 204 curr_mouse_loc_ = event->location(); |
| 188 aura::Window* target = NULL; | 205 aura::Window* target = NULL; |
| 189 // Avoid a call to display::Screen::GetWindowAtScreenPoint() since it can | 206 // Avoid a call to display::Screen::GetWindowAtScreenPoint() since it can |
| 190 // be very expensive on X11 in cases when the tooltip is hidden anyway. | 207 // be very expensive on X11 in cases when the tooltip is hidden anyway. |
| 191 if (tooltips_enabled_ && | 208 if (tooltips_enabled_ && |
| 192 !aura::Env::GetInstance()->IsMouseButtonDown() && | 209 !aura::Env::GetInstance()->IsMouseButtonDown() && |
| 193 !IsDragDropInProgress()) { | 210 !IsDragDropInProgress()) { |
| 194 target = GetTooltipTarget(*event, &curr_mouse_loc_); | 211 target = GetTooltipTarget(*event, &curr_mouse_loc_); |
| 195 } | 212 } |
| 196 SetTooltipWindow(target); | 213 SetTooltipWindow(target); |
| 214 if (tooltip_timer_.IsRunning()) |
| 215 tooltip_timer_.Reset(); |
| 197 | 216 |
| 198 if (tooltip_->IsVisible() || | 217 if (tooltip_->IsVisible()) |
| 199 (tooltip_window_ && | |
| 200 tooltip_text_ != aura::client::GetTooltipText(tooltip_window_))) | |
| 201 UpdateIfRequired(); | 218 UpdateIfRequired(); |
| 202 break; | 219 break; |
| 203 } | 220 } |
| 204 case ui::ET_MOUSE_PRESSED: | 221 case ui::ET_MOUSE_PRESSED: |
| 205 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) { | 222 if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0) { |
| 206 aura::Window* target = static_cast<aura::Window*>(event->target()); | 223 aura::Window* target = static_cast<aura::Window*>(event->target()); |
| 207 // We don't get a release for non-client areas. | 224 // We don't get a release for non-client areas. |
| 208 tooltip_window_at_mouse_press_ = target; | 225 tooltip_window_at_mouse_press_ = target; |
| 209 if (target) | 226 if (target) |
| 210 tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target); | 227 tooltip_text_at_mouse_press_ = aura::client::GetTooltipText(target); |
| 211 } | 228 } |
| 212 tooltip_->Hide(); | 229 tooltip_->Hide(); |
| 213 break; | 230 break; |
| 214 case ui::ET_MOUSEWHEEL: | 231 case ui::ET_MOUSEWHEEL: |
| 215 // Hide the tooltip for click, release, drag, wheel events. | 232 // Hide the tooltip for click, release, drag, wheel events. |
| 216 if (tooltip_->IsVisible()) | 233 if (tooltip_->IsVisible()) |
| 217 tooltip_->Hide(); | 234 tooltip_->Hide(); |
| 235 |
| 236 // Don't reshow the tooltip during scroll. |
| 237 if (tooltip_timer_.IsRunning()) |
| 238 tooltip_timer_.Reset(); |
| 218 break; | 239 break; |
| 219 default: | 240 default: |
| 220 break; | 241 break; |
| 221 } | 242 } |
| 222 } | 243 } |
| 223 | 244 |
| 224 void TooltipController::OnTouchEvent(ui::TouchEvent* event) { | 245 void TooltipController::OnTouchEvent(ui::TouchEvent* event) { |
| 225 // TODO(varunjain): need to properly implement tooltips for | 246 // TODO(varunjain): need to properly implement tooltips for |
| 226 // touch events. | 247 // touch events. |
| 227 // Hide the tooltip for touch events. | 248 // Hide the tooltip for touch events. |
| 228 tooltip_->Hide(); | 249 tooltip_->Hide(); |
| 229 SetTooltipWindow(NULL); | 250 SetTooltipWindow(NULL); |
| 230 } | 251 } |
| 231 | 252 |
| 232 void TooltipController::OnCancelMode(ui::CancelModeEvent* event) { | 253 void TooltipController::OnCancelMode(ui::CancelModeEvent* event) { |
| 233 tooltip_->Hide(); | 254 tooltip_->Hide(); |
| 234 SetTooltipWindow(NULL); | 255 SetTooltipWindow(NULL); |
| 235 } | 256 } |
| 236 | 257 |
| 237 void TooltipController::OnCursorVisibilityChanged(bool is_visible) { | |
| 238 UpdateIfRequired(); | |
| 239 } | |
| 240 | |
| 241 void TooltipController::OnWindowDestroyed(aura::Window* window) { | 258 void TooltipController::OnWindowDestroyed(aura::Window* window) { |
| 242 if (tooltip_window_ == window) { | 259 if (tooltip_window_ == window) { |
| 243 tooltip_->Hide(); | 260 tooltip_->Hide(); |
| 244 tooltip_shown_timeout_map_.erase(tooltip_window_); | 261 tooltip_shown_timeout_map_.erase(tooltip_window_); |
| 245 tooltip_window_ = NULL; | 262 tooltip_window_ = NULL; |
| 246 } | 263 } |
| 247 } | 264 } |
| 248 | 265 |
| 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 aura::client::GetTooltipText(window) != base::string16() && | |
| 255 (tooltip_text_ != aura::client::GetTooltipText(window) || | |
| 256 tooltip_id_ != aura::client::GetTooltipId(window))) | |
| 257 UpdateIfRequired(); | |
| 258 } | |
| 259 | |
| 260 //////////////////////////////////////////////////////////////////////////////// | 266 //////////////////////////////////////////////////////////////////////////////// |
| 261 // TooltipController private: | 267 // TooltipController private: |
| 262 | 268 |
| 269 void TooltipController::TooltipTimerFired() { |
| 270 UpdateIfRequired(); |
| 271 } |
| 272 |
| 263 void TooltipController::TooltipShownTimerFired() { | 273 void TooltipController::TooltipShownTimerFired() { |
| 264 tooltip_->Hide(); | 274 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(); |
| 265 } | 280 } |
| 266 | 281 |
| 267 void TooltipController::UpdateIfRequired() { | 282 void TooltipController::UpdateIfRequired() { |
| 268 if (!tooltips_enabled_ || | 283 if (!tooltips_enabled_ || |
| 269 aura::Env::GetInstance()->IsMouseButtonDown() || | 284 aura::Env::GetInstance()->IsMouseButtonDown() || |
| 270 IsDragDropInProgress() || !IsCursorVisible()) { | 285 IsDragDropInProgress() || !IsCursorVisible()) { |
| 271 tooltip_->Hide(); | 286 tooltip_->Hide(); |
| 272 return; | 287 return; |
| 273 } | 288 } |
| 274 | 289 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 287 tooltip_window_at_mouse_press_ = NULL; | 302 tooltip_window_at_mouse_press_ = NULL; |
| 288 } | 303 } |
| 289 | 304 |
| 290 // If the uniqueness indicator is different from the previously encountered | 305 // If the uniqueness indicator is different from the previously encountered |
| 291 // one, we should force tooltip update | 306 // one, we should force tooltip update |
| 292 const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_); | 307 const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_); |
| 293 bool ids_differ = false; | 308 bool ids_differ = false; |
| 294 ids_differ = tooltip_id_ != tooltip_id; | 309 ids_differ = tooltip_id_ != tooltip_id; |
| 295 tooltip_id_ = tooltip_id; | 310 tooltip_id_ = tooltip_id; |
| 296 | 311 |
| 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. |
| 297 // If we come here from UpdateTooltip(), we have already checked for tooltip | 315 // If we come here from UpdateTooltip(), we have already checked for tooltip |
| 298 // visibility and this check below will have no effect. | 316 // visibility and this check below will have no effect. |
| 299 if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) { | 317 if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) { |
| 300 tooltip_shown_timer_.Stop(); | 318 tooltip_shown_timer_.Stop(); |
| 301 tooltip_text_ = tooltip_text; | 319 tooltip_text_ = tooltip_text; |
| 302 base::string16 trimmed_text = | 320 base::string16 trimmed_text = |
| 303 gfx::TruncateString(tooltip_text_, kMaxTooltipLength, gfx::WORD_BREAK); | 321 gfx::TruncateString(tooltip_text_, kMaxTooltipLength, gfx::WORD_BREAK); |
| 304 // If the string consists entirely of whitespace, then don't both showing it | 322 // If the string consists entirely of whitespace, then don't both showing it |
| 305 // (an empty tooltip is useless). | 323 // (an empty tooltip is useless). |
| 306 base::string16 whitespace_removed_text; | 324 base::string16 whitespace_removed_text; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 return; | 378 return; |
| 361 if (tooltip_window_) | 379 if (tooltip_window_) |
| 362 tooltip_window_->RemoveObserver(this); | 380 tooltip_window_->RemoveObserver(this); |
| 363 tooltip_window_ = target; | 381 tooltip_window_ = target; |
| 364 if (tooltip_window_) | 382 if (tooltip_window_) |
| 365 tooltip_window_->AddObserver(this); | 383 tooltip_window_->AddObserver(this); |
| 366 } | 384 } |
| 367 | 385 |
| 368 } // namespace corewm | 386 } // namespace corewm |
| 369 } // namespace views | 387 } // namespace views |
| OLD | NEW |