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