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 "ash/touch/touch_uma.h" | 5 #include "ash/touch/touch_uma.h" |
| 6 | 6 |
| 7 #include "ash/shell_delegate.h" | 7 #include "ash/shell_delegate.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
| 10 #include "ui/aura/root_window.h" | 10 #include "ui/aura/root_window.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 GESTURE_UNKNOWN, | 23 GESTURE_UNKNOWN, |
| 24 GESTURE_OMNIBOX_PINCH, | 24 GESTURE_OMNIBOX_PINCH, |
| 25 GESTURE_OMNIBOX_SCROLL, | 25 GESTURE_OMNIBOX_SCROLL, |
| 26 GESTURE_TABSTRIP_PINCH, | 26 GESTURE_TABSTRIP_PINCH, |
| 27 GESTURE_TABSTRIP_SCROLL, | 27 GESTURE_TABSTRIP_SCROLL, |
| 28 GESTURE_BEZEL_SCROLL, | 28 GESTURE_BEZEL_SCROLL, |
| 29 GESTURE_DESKTOP_SCROLL, | 29 GESTURE_DESKTOP_SCROLL, |
| 30 GESTURE_DESKTOP_PINCH, | 30 GESTURE_DESKTOP_PINCH, |
| 31 GESTURE_WEBPAGE_PINCH, | 31 GESTURE_WEBPAGE_PINCH, |
| 32 GESTURE_WEBPAGE_SCROLL, | 32 GESTURE_WEBPAGE_SCROLL, |
| 33 GESTURE_WEBPAGE_TAP, | |
| 34 GESTURE_TABSTRIP_TAP, | |
| 35 GESTURE_BEZEL_TAP, | |
| 33 // NOTE: Add new action types only immediately above this line. Also, make sure | 36 // NOTE: Add new action types only immediately above this line. Also, make sure |
| 34 // the enum list in tools/histogram/histograms.xml is updated with any change in | 37 // the enum list in tools/histogram/histograms.xml is updated with any change in |
| 35 // here. | 38 // here. |
| 36 GESTURE_ACTION_COUNT | 39 GESTURE_ACTION_COUNT |
| 37 }; | 40 }; |
| 38 | 41 |
| 39 enum UMAEventType { | 42 enum UMAEventType { |
| 40 UMA_ET_UNKNOWN, | 43 UMA_ET_UNKNOWN, |
| 41 UMA_ET_TOUCH_RELEASED, | 44 UMA_ET_TOUCH_RELEASED, |
| 42 UMA_ET_TOUCH_PRESSED, | 45 UMA_ET_TOUCH_PRESSED, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 | 94 |
| 92 DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowTouchDetails, | 95 DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowTouchDetails, |
| 93 kWindowTouchDetails, | 96 kWindowTouchDetails, |
| 94 NULL); | 97 NULL); |
| 95 | 98 |
| 96 GestureActionType FindGestureActionType(aura::Window* window, | 99 GestureActionType FindGestureActionType(aura::Window* window, |
| 97 const ui::GestureEvent& event) { | 100 const ui::GestureEvent& event) { |
| 98 if (!window || window->GetRootWindow() == window) { | 101 if (!window || window->GetRootWindow() == window) { |
| 99 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 102 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| 100 return GESTURE_BEZEL_SCROLL; | 103 return GESTURE_BEZEL_SCROLL; |
| 104 if (event.type() == ui::ET_GESTURE_TAP) | |
| 105 return GESTURE_BEZEL_TAP; | |
|
sadrul
2012/08/14 05:21:05
rbyers@: Do you think counting long-press here wou
Rick Byers
2012/08/14 05:30:41
Couldn't hurt, but I'm not sure it adds that much
| |
| 101 return GESTURE_UNKNOWN; | 106 return GESTURE_UNKNOWN; |
| 102 } | 107 } |
| 103 | 108 |
| 104 std::string name = window ? window->name() : std::string(); | 109 std::string name = window ? window->name() : std::string(); |
| 105 | 110 |
| 106 const char kDesktopBackgroundView[] = "DesktopBackgroundView"; | 111 const char kDesktopBackgroundView[] = "DesktopBackgroundView"; |
| 107 if (name == kDesktopBackgroundView) { | 112 if (name == kDesktopBackgroundView) { |
| 108 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 113 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| 109 return GESTURE_DESKTOP_SCROLL; | 114 return GESTURE_DESKTOP_SCROLL; |
| 110 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) | 115 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) |
| 111 return GESTURE_DESKTOP_PINCH; | 116 return GESTURE_DESKTOP_PINCH; |
| 112 return GESTURE_UNKNOWN; | 117 return GESTURE_UNKNOWN; |
| 113 } | 118 } |
| 114 | 119 |
| 115 const char kWebPage[] = "RenderWidgetHostViewAura"; | 120 const char kWebPage[] = "RenderWidgetHostViewAura"; |
| 116 if (name == kWebPage) { | 121 if (name == kWebPage) { |
| 117 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) | 122 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) |
| 118 return GESTURE_WEBPAGE_PINCH; | 123 return GESTURE_WEBPAGE_PINCH; |
| 119 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 124 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| 120 return GESTURE_WEBPAGE_SCROLL; | 125 return GESTURE_WEBPAGE_SCROLL; |
| 126 if (event.type() == ui::ET_GESTURE_TAP) | |
| 127 return GESTURE_WEBPAGE_TAP; | |
| 121 return GESTURE_UNKNOWN; | 128 return GESTURE_UNKNOWN; |
| 122 } | 129 } |
| 123 | 130 |
| 124 views::Widget* widget = views::Widget::GetWidgetForNativeView(window); | 131 views::Widget* widget = views::Widget::GetWidgetForNativeView(window); |
| 125 if (!widget) | 132 if (!widget) |
| 126 return GESTURE_UNKNOWN; | 133 return GESTURE_UNKNOWN; |
| 127 | 134 |
| 128 views::View* view = widget->GetRootView()-> | 135 views::View* view = widget->GetRootView()-> |
| 129 GetEventHandlerForPoint(event.location()); | 136 GetEventHandlerForPoint(event.location()); |
| 130 if (!view) | 137 if (!view) |
| 131 return GESTURE_UNKNOWN; | 138 return GESTURE_UNKNOWN; |
| 132 | 139 |
| 133 name = view->GetClassName(); | 140 name = view->GetClassName(); |
| 134 | 141 |
| 135 const char kTabStrip[] = "TabStrip"; | 142 const char kTabStrip[] = "TabStrip"; |
| 136 const char kTab[] = "BrowserTab"; | 143 const char kTab[] = "BrowserTab"; |
| 137 if (name == kTabStrip || name == kTab) { | 144 if (name == kTabStrip || name == kTab) { |
| 138 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 145 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| 139 return GESTURE_TABSTRIP_SCROLL; | 146 return GESTURE_TABSTRIP_SCROLL; |
| 140 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) | 147 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) |
| 141 return GESTURE_TABSTRIP_PINCH; | 148 return GESTURE_TABSTRIP_PINCH; |
| 149 if (event.type() == ui::ET_GESTURE_TAP) | |
| 150 return GESTURE_TABSTRIP_TAP; | |
| 142 return GESTURE_UNKNOWN; | 151 return GESTURE_UNKNOWN; |
| 143 } | 152 } |
| 144 | 153 |
| 145 const char kOmnibox[] = "BrowserOmniboxViewViews"; | 154 const char kOmnibox[] = "BrowserOmniboxViewViews"; |
| 146 if (name == kOmnibox) { | 155 if (name == kOmnibox) { |
| 147 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 156 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| 148 return GESTURE_OMNIBOX_SCROLL; | 157 return GESTURE_OMNIBOX_SCROLL; |
| 149 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) | 158 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) |
| 150 return GESTURE_OMNIBOX_PINCH; | 159 return GESTURE_OMNIBOX_PINCH; |
| 151 return GESTURE_UNKNOWN; | 160 return GESTURE_UNKNOWN; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 static_cast<int>(std::max(event.radius_x(), event.radius_y())), | 275 static_cast<int>(std::max(event.radius_x(), event.radius_y())), |
| 267 1, 500, 100); | 276 1, 500, 100); |
| 268 | 277 |
| 269 WindowTouchDetails* details = target->GetProperty(kWindowTouchDetails); | 278 WindowTouchDetails* details = target->GetProperty(kWindowTouchDetails); |
| 270 if (!details) { | 279 if (!details) { |
| 271 details = new WindowTouchDetails; | 280 details = new WindowTouchDetails; |
| 272 target->SetProperty(kWindowTouchDetails, details); | 281 target->SetProperty(kWindowTouchDetails, details); |
| 273 } | 282 } |
| 274 | 283 |
| 275 // Record the location of the touch points. | 284 // Record the location of the touch points. |
| 276 const int kBucketCount = 100; | 285 const int kBucketCountForLocation = 100; |
| 277 const gfx::Rect bounds = target->GetRootWindow()->bounds(); | 286 const gfx::Rect bounds = target->GetRootWindow()->bounds(); |
| 278 const int bucket_size_x = bounds.width() / kBucketCount; | 287 const int bucket_size_x = bounds.width() / kBucketCountForLocation; |
| 279 const int bucket_size_y = bounds.height() / kBucketCount; | 288 const int bucket_size_y = bounds.height() / kBucketCountForLocation; |
| 280 | 289 |
| 281 gfx::Point position = event.root_location(); | 290 gfx::Point position = event.root_location(); |
| 282 | 291 |
| 283 // Prefer raw event location (when available) over calibrated location. | 292 // Prefer raw event location (when available) over calibrated location. |
| 284 if (event.HasNativeEvent()) { | 293 if (event.HasNativeEvent()) { |
| 285 #if defined(USE_XI2_MT) | 294 #if defined(USE_XI2_MT) |
| 286 XEvent* xevent = event.native_event(); | 295 XEvent* xevent = event.native_event(); |
| 287 CHECK_EQ(GenericEvent, xevent->type); | 296 CHECK_EQ(GenericEvent, xevent->type); |
| 288 XIEvent* xievent = static_cast<XIEvent*>(xevent->xcookie.data); | 297 XIEvent* xievent = static_cast<XIEvent*>(xevent->xcookie.data); |
| 289 if (xievent->evtype == XI_TouchBegin || | 298 if (xievent->evtype == XI_TouchBegin || |
| 290 xievent->evtype == XI_TouchUpdate || | 299 xievent->evtype == XI_TouchUpdate || |
| 291 xievent->evtype == XI_TouchEnd) { | 300 xievent->evtype == XI_TouchEnd) { |
| 292 XIDeviceEvent* device_event = | 301 XIDeviceEvent* device_event = |
| 293 static_cast<XIDeviceEvent*>(xevent->xcookie.data); | 302 static_cast<XIDeviceEvent*>(xevent->xcookie.data); |
| 294 position.SetPoint(static_cast<int>(device_event->event_x), | 303 position.SetPoint(static_cast<int>(device_event->event_x), |
| 295 static_cast<int>(device_event->event_y)); | 304 static_cast<int>(device_event->event_y)); |
| 296 } else { | 305 } else { |
| 297 position = ui::EventLocationFromNative(event.native_event()); | 306 position = ui::EventLocationFromNative(event.native_event()); |
| 298 } | 307 } |
| 299 #else | 308 #else |
| 300 position = ui::EventLocationFromNative(event.native_event()); | 309 position = ui::EventLocationFromNative(event.native_event()); |
| 301 #endif | 310 #endif |
| 302 } | 311 } |
| 303 | 312 |
| 304 position.set_x(std::min(bounds.width() - 1, std::max(0, position.x()))); | 313 position.set_x(std::min(bounds.width() - 1, std::max(0, position.x()))); |
| 305 position.set_y(std::min(bounds.height() - 1, std::max(0, position.y()))); | 314 position.set_y(std::min(bounds.height() - 1, std::max(0, position.y()))); |
| 306 | 315 |
| 307 STATIC_HISTOGRAM_POINTER_BLOCK("Ash.TouchPositionX", | 316 STATIC_HISTOGRAM_POINTER_BLOCK("Ash.TouchPositionX", |
| 308 Add(position.x() / bucket_size_x), | 317 Add(position.x() / bucket_size_x), |
| 309 base::LinearHistogram::FactoryGet("Ash.TouchPositionX", 1, kBucketCount, | 318 base::LinearHistogram::FactoryGet("Ash.TouchPositionX", 0, |
| 310 kBucketCount + 1, base::Histogram::kUmaTargetedHistogramFlag)); | 319 kBucketCountForLocation, kBucketCountForLocation + 1, |
| 320 base::Histogram::kUmaTargetedHistogramFlag)); | |
| 311 STATIC_HISTOGRAM_POINTER_BLOCK("Ash.TouchPositionY", | 321 STATIC_HISTOGRAM_POINTER_BLOCK("Ash.TouchPositionY", |
| 312 Add(position.y() / bucket_size_y), | 322 Add(position.y() / bucket_size_y), |
| 313 base::LinearHistogram::FactoryGet("Ash.TouchPositionY", 1, kBucketCount, | 323 base::LinearHistogram::FactoryGet("Ash.TouchPositionY", 0, |
| 314 kBucketCount + 1, base::Histogram::kUmaTargetedHistogramFlag)); | 324 kBucketCountForLocation, kBucketCountForLocation + 1, |
| 325 base::Histogram::kUmaTargetedHistogramFlag)); | |
|
Ilya Sherman
2012/08/14 05:27:38
As I mentioned on the other CL, I don't think that
sadrul
2012/08/14 05:29:56
We expect that a linear histogram would be more us
Rick Byers
2012/08/14 05:30:41
CUSTOM_COUNTS uses an exponential distribution, ri
Ilya Sherman
2012/08/14 05:45:00
If you create a CUSTOM_COUNTS histogram with 101 b
| |
| 315 | 326 |
| 316 if (event.type() == ui::ET_TOUCH_PRESSED) { | 327 if (event.type() == ui::ET_TOUCH_PRESSED) { |
| 317 Shell::GetInstance()->delegate()->RecordUserMetricsAction( | 328 Shell::GetInstance()->delegate()->RecordUserMetricsAction( |
| 318 UMA_TOUCHSCREEN_TAP_DOWN); | 329 UMA_TOUCHSCREEN_TAP_DOWN); |
| 319 | 330 |
| 320 details->last_start_time_[event.touch_id()] = event.time_stamp(); | 331 details->last_start_time_[event.touch_id()] = event.time_stamp(); |
| 321 details->last_touch_position_[event.touch_id()] = event.location(); | 332 details->last_touch_position_[event.touch_id()] = event.location(); |
| 322 | 333 |
| 323 if (details->last_release_time_.ToInternalValue()) { | 334 if (details->last_release_time_.ToInternalValue()) { |
| 324 // Measuring the interval between a touch-release and the next | 335 // Measuring the interval between a touch-release and the next |
| 325 // touch-start is probably less useful when doing multi-touch (e.g. | 336 // touch-start is probably less useful when doing multi-touch (e.g. |
| 326 // gestures, or multi-touch friendly apps). So count this only if the user | 337 // gestures, or multi-touch friendly apps). So count this only if the user |
| 327 // hasn't done any multi-touch during the last 30 seconds. | 338 // hasn't done any multi-touch during the last 30 seconds. |
| 328 base::TimeDelta diff = event.time_stamp() - details->last_mt_time_; | 339 base::TimeDelta diff = event.time_stamp() - details->last_mt_time_; |
| 329 if (diff.InSeconds() > 30) { | 340 if (diff.InSeconds() > 30) { |
| 330 base::TimeDelta gap = event.time_stamp() - details->last_release_time_; | 341 base::TimeDelta gap = event.time_stamp() - details->last_release_time_; |
| 331 UMA_HISTOGRAM_COUNTS_10000("Ash.TouchStartAfterEnd", | 342 UMA_HISTOGRAM_COUNTS_10000("Ash.TouchStartAfterEnd", |
| 332 gap.InMilliseconds()); | 343 gap.InMilliseconds()); |
| 333 } | 344 } |
| 334 } | 345 } |
| 335 | 346 |
| 336 // Record the number of touch-points currently active for the window. | 347 // Record the number of touch-points currently active for the window. |
| 337 const int kMaxTouchPoints = 10; | 348 const int kMaxTouchPoints = 10; |
| 338 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.ActiveTouchPoints", | 349 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.ActiveTouchPoints", |
| 339 std::min(static_cast<int>(details->last_start_time_.size()), | 350 details->last_start_time_.size(), |
| 340 kMaxTouchPoints), | |
| 341 1, kMaxTouchPoints, kMaxTouchPoints); | 351 1, kMaxTouchPoints, kMaxTouchPoints); |
| 342 } else if (event.type() == ui::ET_TOUCH_RELEASED) { | 352 } else if (event.type() == ui::ET_TOUCH_RELEASED) { |
| 343 if (details->last_start_time_.count(event.touch_id())) { | 353 if (details->last_start_time_.count(event.touch_id())) { |
| 344 base::TimeDelta duration = event.time_stamp() - | 354 base::TimeDelta duration = event.time_stamp() - |
| 345 details->last_start_time_[event.touch_id()]; | 355 details->last_start_time_[event.touch_id()]; |
| 346 UMA_HISTOGRAM_COUNTS_100("Ash.TouchDuration", duration.InMilliseconds()); | 356 UMA_HISTOGRAM_COUNTS_100("Ash.TouchDuration", duration.InMilliseconds()); |
| 347 } | 357 } |
| 348 details->last_start_time_.erase(event.touch_id()); | 358 details->last_start_time_.erase(event.touch_id()); |
| 349 details->last_move_time_.erase(event.touch_id()); | 359 details->last_move_time_.erase(event.touch_id()); |
| 350 details->last_touch_position_.erase(event.touch_id()); | 360 details->last_touch_position_.erase(event.touch_id()); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 366 | 376 |
| 367 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchMoveSteps", distance, 1, 1000, 50); | 377 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchMoveSteps", distance, 1, 1000, 50); |
| 368 | 378 |
| 369 details->last_move_time_[event.touch_id()] = event.time_stamp(); | 379 details->last_move_time_[event.touch_id()] = event.time_stamp(); |
| 370 details->last_touch_position_[event.touch_id()] = event.location(); | 380 details->last_touch_position_[event.touch_id()] = event.location(); |
| 371 } | 381 } |
| 372 } | 382 } |
| 373 | 383 |
| 374 } // namespace internal | 384 } // namespace internal |
| 375 } // namespace ash | 385 } // namespace ash |
| OLD | NEW |