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 27namespace { 28 29base::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 47gfx::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 58std::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 110bool 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 120namespace ui { 121 122//////////////////////////////////////////////////////////////////////////////// 123// Event 124 125Event::~Event() { 126#if defined(USE_X11) 127 if (delete_native_event_) 128 delete native_event_; 129#endif 130} 131 132bool 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 138void 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 146void 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 154Event::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 172Event::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 202Event::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 222void 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 230void Event::Init() { 231 std::memset(&native_event_, 0, sizeof(native_event_)); 232} 233 234void Event::InitWithNativeEvent(const base::NativeEvent& native_event) { 235 native_event_ = native_event; 236} 237 238void 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 251CancelModeEvent::CancelModeEvent() 252 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) { 253 set_cancelable(false); 254} 255 256CancelModeEvent::~CancelModeEvent() { 257} 258 259//////////////////////////////////////////////////////////////////////////////// 260// LocatedEvent 261 262LocatedEvent::~LocatedEvent() { 263} 264 265LocatedEvent::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 273LocatedEvent::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 283void 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 294MouseEvent::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 302MouseEvent::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 313bool 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 345int 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 362MouseEvent* MouseEvent::last_click_event_ = NULL; 363 364int 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 376void 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 404MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event) 405 : MouseEvent(native_event), 406 offset_(GetMouseWheelOffset(native_event)) { 407} 408 409MouseWheelEvent::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 415MouseWheelEvent::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 422MouseWheelEvent::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 431const int MouseWheelEvent::kWheelDelta = 120; 432#else 433// This value matches GTK+ wheel scroll amount. 434const int MouseWheelEvent::kWheelDelta = 53; 435#endif 436 437void 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 452TouchEvent::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 462TouchEvent::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 475TouchEvent::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 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 is_char_(is_char), 527 character_(0), 528 unmodified_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 unmodified_character_(0) { 543} 544 545uint16 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 569uint16 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 602KeyEvent* 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 610bool 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 626void 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 653TranslatedKeyEvent::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 660TranslatedKeyEvent::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 669void TranslatedKeyEvent::ConvertToKeyEvent() { 670 SetType(type() == ET_TRANSLATED_KEY_PRESS ? 671 ET_KEY_PRESSED : ET_KEY_RELEASED); 672} 673 674//////////////////////////////////////////////////////////////////////////////// 675// DropTargetEvent 676 677DropTargetEvent::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 693ScrollEvent::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 712ScrollEvent::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 731void 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 738void 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 753GestureEvent::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 769GestureEvent::~GestureEvent() { 770} 771 772int 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