event.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 3// found in the LICENSE file. 4 5#include "ui/events/event.h" 6 7#if defined(USE_X11) 8#include <X11/extensions/XInput2.h> 9#include <X11/Xlib.h> 10#endif 11 12#include <cmath> 13#include <cstring> 14 15#include "base/metrics/histogram.h" 16#include "base/strings/stringprintf.h" 17#include "ui/events/event_utils.h" 18#include "ui/events/keycodes/keyboard_code_conversion.h" 19#include "ui/gfx/point3_f.h" 20#include "ui/gfx/point_conversions.h" 21#include "ui/gfx/transform.h" 22#include "ui/gfx/transform_util.h" 23 24#if defined(USE_X11) 25#include "ui/events/keycodes/keyboard_code_conversion_x.h" 26#elif defined(USE_OZONE) 27#include "ui/events/keycodes/keyboard_code_conversion.h" 28#endif 29 30namespace { 31 32base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) { 33#if defined(USE_X11) 34 if (!event || event->type == GenericEvent) 35 return NULL; 36 XEvent* copy = new XEvent; 37 *copy = *event; 38 return copy; 39#elif defined(OS_WIN) 40 return event; 41#elif defined(USE_OZONE) 42 return NULL; 43#else 44 NOTREACHED() << 45 "Don't know how to copy base::NativeEvent for this platform"; 46 return NULL; 47#endif 48} 49 50std::string EventTypeName(ui::EventType type) { 51#define RETURN_IF_TYPE(t) if (type == ui::t) return #t 52#define CASE_TYPE(t) case ui::t: return #t 53 switch (type) { 54 CASE_TYPE(ET_UNKNOWN); 55 CASE_TYPE(ET_MOUSE_PRESSED); 56 CASE_TYPE(ET_MOUSE_DRAGGED); 57 CASE_TYPE(ET_MOUSE_RELEASED); 58 CASE_TYPE(ET_MOUSE_MOVED); 59 CASE_TYPE(ET_MOUSE_ENTERED); 60 CASE_TYPE(ET_MOUSE_EXITED); 61 CASE_TYPE(ET_KEY_PRESSED); 62 CASE_TYPE(ET_KEY_RELEASED); 63 CASE_TYPE(ET_MOUSEWHEEL); 64 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED); 65 CASE_TYPE(ET_TOUCH_RELEASED); 66 CASE_TYPE(ET_TOUCH_PRESSED); 67 CASE_TYPE(ET_TOUCH_MOVED); 68 CASE_TYPE(ET_TOUCH_STATIONARY); 69 CASE_TYPE(ET_TOUCH_CANCELLED); 70 CASE_TYPE(ET_DROP_TARGET_EVENT); 71 CASE_TYPE(ET_TRANSLATED_KEY_PRESS); 72 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE); 73 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN); 74 CASE_TYPE(ET_GESTURE_SCROLL_END); 75 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE); 76 CASE_TYPE(ET_GESTURE_SHOW_PRESS); 77 CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE); 78 CASE_TYPE(ET_GESTURE_TAP); 79 CASE_TYPE(ET_GESTURE_TAP_DOWN); 80 CASE_TYPE(ET_GESTURE_TAP_CANCEL); 81 CASE_TYPE(ET_GESTURE_BEGIN); 82 CASE_TYPE(ET_GESTURE_END); 83 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP); 84 CASE_TYPE(ET_GESTURE_PINCH_BEGIN); 85 CASE_TYPE(ET_GESTURE_PINCH_END); 86 CASE_TYPE(ET_GESTURE_PINCH_UPDATE); 87 CASE_TYPE(ET_GESTURE_LONG_PRESS); 88 CASE_TYPE(ET_GESTURE_LONG_TAP); 89 CASE_TYPE(ET_GESTURE_MULTIFINGER_SWIPE); 90 CASE_TYPE(ET_SCROLL); 91 CASE_TYPE(ET_SCROLL_FLING_START); 92 CASE_TYPE(ET_SCROLL_FLING_CANCEL); 93 CASE_TYPE(ET_CANCEL_MODE); 94 CASE_TYPE(ET_UMA_DATA); 95 case ui::ET_LAST: NOTREACHED(); return std::string(); 96 // Don't include default, so that we get an error when new type is added. 97 } 98#undef CASE_TYPE 99 100 NOTREACHED(); 101 return std::string(); 102} 103 104bool IsX11SendEventTrue(const base::NativeEvent& event) { 105#if defined(USE_X11) 106 if (event && event->xany.send_event) 107 return true; 108#endif 109 return false; 110} 111 112} // namespace 113 114namespace ui { 115 116//////////////////////////////////////////////////////////////////////////////// 117// Event 118 119Event::~Event() { 120#if defined(USE_X11) 121 if (delete_native_event_) 122 delete native_event_; 123#endif 124} 125 126bool Event::HasNativeEvent() const { 127 base::NativeEvent null_event; 128 std::memset(&null_event, 0, sizeof(null_event)); 129 return !!std::memcmp(&native_event_, &null_event, sizeof(null_event)); 130} 131 132void Event::StopPropagation() { 133 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch 134 // events. 135 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH); 136 CHECK(cancelable_); 137 result_ = static_cast<EventResult>(result_ | ER_CONSUMED); 138} 139 140void Event::SetHandled() { 141 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch 142 // events. 143 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH); 144 CHECK(cancelable_); 145 result_ = static_cast<EventResult>(result_ | ER_HANDLED); 146} 147 148Event::Event(EventType type, base::TimeDelta time_stamp, int flags) 149 : type_(type), 150 time_stamp_(time_stamp), 151 flags_(flags), 152#if defined(USE_X11) 153 native_event_(NULL), 154#endif 155 delete_native_event_(false), 156 cancelable_(true), 157 target_(NULL), 158 phase_(EP_PREDISPATCH), 159 result_(ER_UNHANDLED) { 160 if (type_ < ET_LAST) 161 name_ = EventTypeName(type_); 162 Init(); 163} 164 165Event::Event(const base::NativeEvent& native_event, 166 EventType type, 167 int flags) 168 : type_(type), 169 time_stamp_(EventTimeFromNative(native_event)), 170 flags_(flags), 171 delete_native_event_(false), 172 cancelable_(true), 173 target_(NULL), 174 phase_(EP_PREDISPATCH), 175 result_(ER_UNHANDLED) { 176 base::TimeDelta delta = EventTimeForNow() - time_stamp_; 177 if (type_ < ET_LAST) 178 name_ = EventTypeName(type_); 179 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", 180 delta.InMicroseconds(), 1, 1000000, 100); 181 std::string name_for_event = 182 base::StringPrintf("Event.Latency.Browser.%s", name_.c_str()); 183 base::HistogramBase* counter_for_type = 184 base::Histogram::FactoryGet( 185 name_for_event, 186 1, 187 1000000, 188 100, 189 base::HistogramBase::kUmaTargetedHistogramFlag); 190 counter_for_type->Add(delta.InMicroseconds()); 191 InitWithNativeEvent(native_event); 192} 193 194Event::Event(const Event& copy) 195 : type_(copy.type_), 196 time_stamp_(copy.time_stamp_), 197 latency_(copy.latency_), 198 flags_(copy.flags_), 199 native_event_(::CopyNativeEvent(copy.native_event_)), 200 delete_native_event_(false), 201 cancelable_(true), 202 target_(NULL), 203 phase_(EP_PREDISPATCH), 204 result_(ER_UNHANDLED) { 205 if (type_ < ET_LAST) 206 name_ = EventTypeName(type_); 207#if defined(USE_X11) 208 if (native_event_) 209 delete_native_event_ = true; 210#endif 211} 212 213void Event::SetType(EventType type) { 214 if (type_ < ET_LAST) 215 name_ = std::string(); 216 type_ = type; 217 if (type_ < ET_LAST) 218 name_ = EventTypeName(type_); 219} 220 221void Event::Init() { 222 std::memset(&native_event_, 0, sizeof(native_event_)); 223} 224 225void Event::InitWithNativeEvent(const base::NativeEvent& native_event) { 226 native_event_ = native_event; 227} 228 229//////////////////////////////////////////////////////////////////////////////// 230// CancelModeEvent 231 232CancelModeEvent::CancelModeEvent() 233 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) { 234 set_cancelable(false); 235} 236 237CancelModeEvent::~CancelModeEvent() { 238} 239 240//////////////////////////////////////////////////////////////////////////////// 241// LocatedEvent 242 243LocatedEvent::~LocatedEvent() { 244} 245 246LocatedEvent::LocatedEvent(const base::NativeEvent& native_event) 247 : Event(native_event, 248 EventTypeFromNative(native_event), 249 EventFlagsFromNative(native_event)), 250 location_(EventLocationFromNative(native_event)), 251 root_location_(location_) { 252} 253 254LocatedEvent::LocatedEvent(EventType type, 255 const gfx::PointF& location, 256 const gfx::PointF& root_location, 257 base::TimeDelta time_stamp, 258 int flags) 259 : Event(type, time_stamp, flags), 260 location_(location), 261 root_location_(root_location) { 262} 263 264void LocatedEvent::UpdateForRootTransform( 265 const gfx::Transform& reversed_root_transform) { 266 // Transform has to be done at root level. 267 gfx::Point3F p(location_); 268 reversed_root_transform.TransformPoint(&p); 269 location_ = p.AsPointF(); 270 root_location_ = location_; 271} 272 273//////////////////////////////////////////////////////////////////////////////// 274// MouseEvent 275 276MouseEvent::MouseEvent(const base::NativeEvent& native_event) 277 : LocatedEvent(native_event), 278 changed_button_flags_( 279 GetChangedMouseButtonFlagsFromNative(native_event)) { 280 if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED) 281 SetClickCount(GetRepeatCount(*this)); 282} 283 284MouseEvent::MouseEvent(EventType type, 285 const gfx::PointF& location, 286 const gfx::PointF& root_location, 287 int flags, 288 int changed_button_flags) 289 : LocatedEvent(type, location, root_location, EventTimeForNow(), flags), 290 changed_button_flags_(changed_button_flags) { 291 if (this->type() == ET_MOUSE_MOVED && IsAnyButton()) 292 SetType(ET_MOUSE_DRAGGED); 293} 294 295// static 296bool MouseEvent::IsRepeatedClickEvent( 297 const MouseEvent& event1, 298 const MouseEvent& event2) { 299 // These values match the Windows defaults. 300 static const int kDoubleClickTimeMS = 500; 301 static const int kDoubleClickWidth = 4; 302 static const int kDoubleClickHeight = 4; 303 304 if (event1.type() != ET_MOUSE_PRESSED || 305 event2.type() != ET_MOUSE_PRESSED) 306 return false; 307 308 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks. 309 if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) != 310 (event2.flags() & ~EF_IS_DOUBLE_CLICK)) 311 return false; 312 313 base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp(); 314 315 if (time_difference.InMilliseconds() > kDoubleClickTimeMS) 316 return false; 317 318 if (abs(event2.x() - event1.x()) > kDoubleClickWidth / 2) 319 return false; 320 321 if (abs(event2.y() - event1.y()) > kDoubleClickHeight / 2) 322 return false; 323 324 return true; 325} 326 327// static 328int MouseEvent::GetRepeatCount(const MouseEvent& event) { 329 int click_count = 1; 330 if (last_click_event_) { 331 if (event.type() == ui::ET_MOUSE_RELEASED) 332 return last_click_event_->GetClickCount(); 333 if (IsX11SendEventTrue(event.native_event())) 334 click_count = last_click_event_->GetClickCount(); 335 else if (IsRepeatedClickEvent(*last_click_event_, event)) 336 click_count = last_click_event_->GetClickCount() + 1; 337 delete last_click_event_; 338 } 339 last_click_event_ = new MouseEvent(event); 340 if (click_count > 3) 341 click_count = 3; 342 last_click_event_->SetClickCount(click_count); 343 return click_count; 344} 345 346// static 347MouseEvent* MouseEvent::last_click_event_ = NULL; 348 349int MouseEvent::GetClickCount() const { 350 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 351 return 0; 352 353 if (flags() & EF_IS_TRIPLE_CLICK) 354 return 3; 355 else if (flags() & EF_IS_DOUBLE_CLICK) 356 return 2; 357 else 358 return 1; 359} 360 361void MouseEvent::SetClickCount(int click_count) { 362 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 363 return; 364 365 DCHECK(click_count > 0); 366 DCHECK(click_count <= 3); 367 368 int f = flags(); 369 switch (click_count) { 370 case 1: 371 f &= ~EF_IS_DOUBLE_CLICK; 372 f &= ~EF_IS_TRIPLE_CLICK; 373 break; 374 case 2: 375 f |= EF_IS_DOUBLE_CLICK; 376 f &= ~EF_IS_TRIPLE_CLICK; 377 break; 378 case 3: 379 f &= ~EF_IS_DOUBLE_CLICK; 380 f |= EF_IS_TRIPLE_CLICK; 381 break; 382 } 383 set_flags(f); 384} 385 386//////////////////////////////////////////////////////////////////////////////// 387// MouseWheelEvent 388 389MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event) 390 : MouseEvent(native_event), 391 offset_(GetMouseWheelOffset(native_event)) { 392} 393 394MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event) 395 : MouseEvent(scroll_event), 396 offset_(scroll_event.x_offset(), scroll_event.y_offset()){ 397 SetType(ET_MOUSEWHEEL); 398} 399 400MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event, 401 int x_offset, 402 int y_offset) 403 : MouseEvent(mouse_event), offset_(x_offset, y_offset) { 404 DCHECK(type() == ET_MOUSEWHEEL); 405} 406 407MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event) 408 : MouseEvent(mouse_wheel_event), 409 offset_(mouse_wheel_event.offset()) { 410 DCHECK(type() == ET_MOUSEWHEEL); 411} 412 413#if defined(OS_WIN) 414// This value matches windows WHEEL_DELTA. 415// static 416const int MouseWheelEvent::kWheelDelta = 120; 417#else 418// This value matches GTK+ wheel scroll amount. 419const int MouseWheelEvent::kWheelDelta = 53; 420#endif 421 422void MouseWheelEvent::UpdateForRootTransform( 423 const gfx::Transform& inverted_root_transform) { 424 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 425 gfx::DecomposedTransform decomp; 426 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 427 DCHECK(success); 428 if (decomp.scale[0]) 429 offset_.set_x(offset_.x() * decomp.scale[0]); 430 if (decomp.scale[1]) 431 offset_.set_y(offset_.y() * decomp.scale[1]); 432} 433 434//////////////////////////////////////////////////////////////////////////////// 435// TouchEvent 436 437TouchEvent::TouchEvent(const base::NativeEvent& native_event) 438 : LocatedEvent(native_event), 439 touch_id_(GetTouchId(native_event)), 440 radius_x_(GetTouchRadiusX(native_event)), 441 radius_y_(GetTouchRadiusY(native_event)), 442 rotation_angle_(GetTouchAngle(native_event)), 443 force_(GetTouchForce(native_event)), 444 source_device_id_(-1) { 445 latency()->AddLatencyNumberWithTimestamp( 446 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 447 0, 448 0, 449 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 450 1); 451 452#if defined(USE_X11) 453 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(native_event->xcookie.data); 454 source_device_id_ = xiev->deviceid; 455#endif 456 457 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 458} 459 460TouchEvent::TouchEvent(EventType type, 461 const gfx::PointF& location, 462 int touch_id, 463 base::TimeDelta time_stamp) 464 : LocatedEvent(type, location, location, time_stamp, 0), 465 touch_id_(touch_id), 466 radius_x_(0.0f), 467 radius_y_(0.0f), 468 rotation_angle_(0.0f), 469 force_(0.0f), 470 source_device_id_(-1) { 471 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 472} 473 474TouchEvent::TouchEvent(EventType type, 475 const gfx::PointF& location, 476 int flags, 477 int touch_id, 478 base::TimeDelta time_stamp, 479 float radius_x, 480 float radius_y, 481 float angle, 482 float force) 483 : LocatedEvent(type, location, location, time_stamp, flags), 484 touch_id_(touch_id), 485 radius_x_(radius_x), 486 radius_y_(radius_y), 487 rotation_angle_(angle), 488 force_(force), 489 source_device_id_(-1) { 490 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 491} 492 493TouchEvent::~TouchEvent() { 494 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11 495 // platform setups the tracking_id to slot mapping. So in dtor here, 496 // if this touch event is a release event, we clear the mapping accordingly. 497 if (HasNativeEvent()) 498 ClearTouchIdIfReleased(native_event()); 499} 500 501void TouchEvent::Relocate(const gfx::Point& origin) { 502 location_ -= origin.OffsetFromOrigin(); 503 root_location_ -= origin.OffsetFromOrigin(); 504} 505 506void TouchEvent::UpdateForRootTransform( 507 const gfx::Transform& inverted_root_transform) { 508 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 509 gfx::DecomposedTransform decomp; 510 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 511 DCHECK(success); 512 if (decomp.scale[0]) 513 radius_x_ *= decomp.scale[0]; 514 if (decomp.scale[1]) 515 radius_y_ *= decomp.scale[1]; 516} 517 518//////////////////////////////////////////////////////////////////////////////// 519// KeyEvent 520 521KeyEvent::KeyEvent(const base::NativeEvent& native_event, bool is_char) 522 : Event(native_event, 523 EventTypeFromNative(native_event), 524 EventFlagsFromNative(native_event)), 525 key_code_(KeyboardCodeFromNative(native_event)), 526 code_(CodeFromNative(native_event)), 527 is_char_(is_char), 528 character_(0) { 529#if defined(USE_X11) 530 NormalizeFlags(); 531#endif 532} 533 534KeyEvent::KeyEvent(EventType type, 535 KeyboardCode key_code, 536 int flags, 537 bool is_char) 538 : Event(type, EventTimeForNow(), flags), 539 key_code_(key_code), 540 is_char_(is_char), 541 character_(GetCharacterFromKeyCode(key_code, flags)) { 542} 543 544KeyEvent::KeyEvent(EventType type, 545 KeyboardCode key_code, 546 const std::string& code, 547 int flags, 548 bool is_char) 549 : Event(type, EventTimeForNow(), flags), 550 key_code_(key_code), 551 code_(code), 552 is_char_(is_char), 553 character_(GetCharacterFromKeyCode(key_code, flags)) { 554} 555 556uint16 KeyEvent::GetCharacter() const { 557 if (character_) 558 return character_; 559 560#if defined(OS_WIN) 561 return (native_event().message == WM_CHAR) ? key_code_ : 562 GetCharacterFromKeyCode(key_code_, flags()); 563#elif defined(USE_X11) 564 if (!native_event()) 565 return GetCharacterFromKeyCode(key_code_, flags()); 566 567 DCHECK(native_event()->type == KeyPress || 568 native_event()->type == KeyRelease); 569 570 uint16 ch = 0; 571 if (!IsControlDown()) 572 ch = GetCharacterFromXEvent(native_event()); 573 return ch ? ch : GetCharacterFromKeyCode(key_code_, flags()); 574#else 575 if (native_event()) { 576 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED || 577 EventTypeFromNative(native_event()) == ET_KEY_RELEASED); 578 } 579 580 return GetCharacterFromKeyCode(key_code_, flags()); 581#endif 582} 583 584bool KeyEvent::IsUnicodeKeyCode() const { 585 if (!IsAltDown()) 586 return false; 587 const int key = key_code(); 588 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9) 589 return true; 590 // Check whether the user is using the numeric keypad with num-lock off. 591 // In that case, EF_EXTENDED will not be set; if it is set, the key event 592 // originated from the relevant non-numpad dedicated key, e.g. [Insert]. 593 return (!(flags() & EF_EXTENDED) && 594 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN || 595 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR || 596 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP || 597 key == VKEY_PRIOR)); 598} 599 600void KeyEvent::NormalizeFlags() { 601 int mask = 0; 602 switch (key_code()) { 603 case VKEY_CONTROL: 604 mask = EF_CONTROL_DOWN; 605 break; 606 case VKEY_SHIFT: 607 mask = EF_SHIFT_DOWN; 608 break; 609 case VKEY_MENU: 610 mask = EF_ALT_DOWN; 611 break; 612 case VKEY_CAPITAL: 613 mask = EF_CAPS_LOCK_DOWN; 614 break; 615 default: 616 return; 617 } 618 if (type() == ET_KEY_PRESSED) 619 set_flags(flags() | mask); 620 else 621 set_flags(flags() & ~mask); 622} 623 624//////////////////////////////////////////////////////////////////////////////// 625// TranslatedKeyEvent 626 627TranslatedKeyEvent::TranslatedKeyEvent(const base::NativeEvent& native_event, 628 bool is_char) 629 : KeyEvent(native_event, is_char) { 630 SetType(type() == ET_KEY_PRESSED ? 631 ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE); 632} 633 634TranslatedKeyEvent::TranslatedKeyEvent(bool is_press, 635 KeyboardCode key_code, 636 int flags) 637 : KeyEvent((is_press ? ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE), 638 key_code, 639 flags, 640 false) { 641} 642 643TranslatedKeyEvent::TranslatedKeyEvent(const KeyEvent& key_event) 644 : KeyEvent(key_event) { 645 SetType(type() == ET_KEY_PRESSED ? 646 ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE); 647 set_is_char(false); 648} 649 650void TranslatedKeyEvent::ConvertToKeyEvent() { 651 SetType(type() == ET_TRANSLATED_KEY_PRESS ? 652 ET_KEY_PRESSED : ET_KEY_RELEASED); 653} 654 655//////////////////////////////////////////////////////////////////////////////// 656// ScrollEvent 657 658ScrollEvent::ScrollEvent(const base::NativeEvent& native_event) 659 : MouseEvent(native_event) { 660 if (type() == ET_SCROLL) { 661 GetScrollOffsets(native_event, 662 &x_offset_, &y_offset_, 663 &x_offset_ordinal_, &y_offset_ordinal_, 664 &finger_count_); 665 } else if (type() == ET_SCROLL_FLING_START || 666 type() == ET_SCROLL_FLING_CANCEL) { 667 GetFlingData(native_event, 668 &x_offset_, &y_offset_, 669 &x_offset_ordinal_, &y_offset_ordinal_, 670 NULL); 671 } else { 672 NOTREACHED() << "Unexpected event type " << type() 673 << " when constructing a ScrollEvent."; 674 } 675} 676 677ScrollEvent::ScrollEvent(EventType type, 678 const gfx::PointF& location, 679 base::TimeDelta time_stamp, 680 int flags, 681 float x_offset, 682 float y_offset, 683 float x_offset_ordinal, 684 float y_offset_ordinal, 685 int finger_count) 686 : MouseEvent(type, location, location, flags, 0), 687 x_offset_(x_offset), 688 y_offset_(y_offset), 689 x_offset_ordinal_(x_offset_ordinal), 690 y_offset_ordinal_(y_offset_ordinal), 691 finger_count_(finger_count) { 692 set_time_stamp(time_stamp); 693 CHECK(IsScrollEvent()); 694} 695 696void ScrollEvent::Scale(const float factor) { 697 x_offset_ *= factor; 698 y_offset_ *= factor; 699 x_offset_ordinal_ *= factor; 700 y_offset_ordinal_ *= factor; 701} 702 703//////////////////////////////////////////////////////////////////////////////// 704// GestureEvent 705 706GestureEvent::GestureEvent(EventType type, 707 float x, 708 float y, 709 int flags, 710 base::TimeDelta time_stamp, 711 const GestureEventDetails& details, 712 unsigned int touch_ids_bitfield) 713 : LocatedEvent(type, 714 gfx::PointF(x, y), 715 gfx::PointF(x, y), 716 time_stamp, 717 flags | EF_FROM_TOUCH), 718 details_(details), 719 touch_ids_bitfield_(touch_ids_bitfield) { 720} 721 722GestureEvent::~GestureEvent() { 723} 724 725int GestureEvent::GetLowestTouchId() const { 726 if (touch_ids_bitfield_ == 0) 727 return -1; 728 int i = -1; 729 // Find the index of the least significant 1 bit 730 while (!(1 << ++i & touch_ids_bitfield_)); 731 return i; 732} 733 734} // namespace ui 735