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