event.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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/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/events/event_utils.h" 17#include "ui/events/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/events/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 NULL; 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 || type() == ET_MOUSE_RELEASED) 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 (event.type() == ui::ET_MOUSE_RELEASED) 349 return last_click_event_->GetClickCount(); 350 if (IsX11SendEventTrue(event.native_event())) 351 click_count = last_click_event_->GetClickCount(); 352 else if (IsRepeatedClickEvent(*last_click_event_, event)) 353 click_count = last_click_event_->GetClickCount() + 1; 354 delete last_click_event_; 355 } 356 last_click_event_ = new MouseEvent(event); 357 if (click_count > 3) 358 click_count = 3; 359 last_click_event_->SetClickCount(click_count); 360 return click_count; 361} 362 363// static 364MouseEvent* MouseEvent::last_click_event_ = NULL; 365 366int MouseEvent::GetClickCount() const { 367 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 368 return 0; 369 370 if (flags() & EF_IS_TRIPLE_CLICK) 371 return 3; 372 else if (flags() & EF_IS_DOUBLE_CLICK) 373 return 2; 374 else 375 return 1; 376} 377 378void MouseEvent::SetClickCount(int click_count) { 379 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 380 return; 381 382 DCHECK(click_count > 0); 383 DCHECK(click_count <= 3); 384 385 int f = flags(); 386 switch (click_count) { 387 case 1: 388 f &= ~EF_IS_DOUBLE_CLICK; 389 f &= ~EF_IS_TRIPLE_CLICK; 390 break; 391 case 2: 392 f |= EF_IS_DOUBLE_CLICK; 393 f &= ~EF_IS_TRIPLE_CLICK; 394 break; 395 case 3: 396 f &= ~EF_IS_DOUBLE_CLICK; 397 f |= EF_IS_TRIPLE_CLICK; 398 break; 399 } 400 set_flags(f); 401} 402 403//////////////////////////////////////////////////////////////////////////////// 404// MouseWheelEvent 405 406MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event) 407 : MouseEvent(native_event), 408 offset_(GetMouseWheelOffset(native_event)) { 409} 410 411MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event) 412 : MouseEvent(scroll_event), 413 offset_(scroll_event.x_offset(), scroll_event.y_offset()){ 414 SetType(ET_MOUSEWHEEL); 415} 416 417MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event, 418 int x_offset, 419 int y_offset) 420 : MouseEvent(mouse_event), offset_(x_offset, y_offset) { 421 DCHECK(type() == ET_MOUSEWHEEL); 422} 423 424MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event) 425 : MouseEvent(mouse_wheel_event), 426 offset_(mouse_wheel_event.offset()) { 427 DCHECK(type() == ET_MOUSEWHEEL); 428} 429 430#if defined(OS_WIN) 431// This value matches windows WHEEL_DELTA. 432// static 433const int MouseWheelEvent::kWheelDelta = 120; 434#else 435// This value matches GTK+ wheel scroll amount. 436const int MouseWheelEvent::kWheelDelta = 53; 437#endif 438 439void MouseWheelEvent::UpdateForRootTransform( 440 const gfx::Transform& inverted_root_transform) { 441 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 442 gfx::DecomposedTransform decomp; 443 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 444 DCHECK(success); 445 if (decomp.scale[0]) 446 offset_.set_x(offset_.x() * decomp.scale[0]); 447 if (decomp.scale[1]) 448 offset_.set_y(offset_.y() * decomp.scale[1]); 449} 450 451//////////////////////////////////////////////////////////////////////////////// 452// TouchEvent 453 454TouchEvent::TouchEvent(const base::NativeEvent& native_event) 455 : LocatedEvent(native_event), 456 touch_id_(GetTouchId(native_event)), 457 radius_x_(GetTouchRadiusX(native_event)), 458 radius_y_(GetTouchRadiusY(native_event)), 459 rotation_angle_(GetTouchAngle(native_event)), 460 force_(GetTouchForce(native_event)) { 461 InitLatencyInfo(); 462} 463 464TouchEvent::TouchEvent(EventType type, 465 const gfx::Point& location, 466 int touch_id, 467 base::TimeDelta time_stamp) 468 : LocatedEvent(type, location, location, time_stamp, 0), 469 touch_id_(touch_id), 470 radius_x_(0.0f), 471 radius_y_(0.0f), 472 rotation_angle_(0.0f), 473 force_(0.0f) { 474 InitLatencyInfo(); 475} 476 477TouchEvent::TouchEvent(EventType type, 478 const gfx::Point& location, 479 int flags, 480 int touch_id, 481 base::TimeDelta time_stamp, 482 float radius_x, 483 float radius_y, 484 float angle, 485 float force) 486 : LocatedEvent(type, location, location, time_stamp, flags), 487 touch_id_(touch_id), 488 radius_x_(radius_x), 489 radius_y_(radius_y), 490 rotation_angle_(angle), 491 force_(force) { 492 InitLatencyInfo(); 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 is_char_(is_char), 529 character_(0), 530 unmodified_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 unmodified_character_(0) { 545} 546 547uint16 KeyEvent::GetCharacter() const { 548 if (character_) 549 return character_; 550 551#if defined(OS_WIN) 552 return (native_event().message == WM_CHAR) ? key_code_ : 553 GetCharacterFromKeyCode(key_code_, flags()); 554#elif defined(USE_X11) 555 if (!native_event()) 556 return GetCharacterFromKeyCode(key_code_, flags()); 557 558 DCHECK(native_event()->type == KeyPress || 559 native_event()->type == KeyRelease); 560 561 uint16 ch = 0; 562 if (!IsControlDown()) 563 ch = GetCharacterFromXEvent(native_event()); 564 return ch ? ch : GetCharacterFromKeyCode(key_code_, flags()); 565#else 566 NOTIMPLEMENTED(); 567 return 0; 568#endif 569} 570 571uint16 KeyEvent::GetUnmodifiedCharacter() const { 572 if (unmodified_character_) 573 return unmodified_character_; 574 575#if defined(OS_WIN) 576 // Looks like there is no way to get unmodified character on Windows. 577 return (native_event().message == WM_CHAR) ? key_code_ : 578 GetCharacterFromKeyCode(key_code_, flags() & EF_SHIFT_DOWN); 579#elif defined(USE_X11) 580 if (!native_event()) 581 return GetCharacterFromKeyCode(key_code_, flags() & EF_SHIFT_DOWN); 582 583 DCHECK(native_event()->type == KeyPress || 584 native_event()->type == KeyRelease); 585 586 static const unsigned int kIgnoredModifiers = ControlMask | LockMask | 587 Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask; 588 589 XKeyEvent copy = native_event()->xkey; // bit-wise copy is safe. 590 // We can't use things like (native_event()->xkey.state & ShiftMask), as it 591 // may mask out bits used by X11 internally. 592 copy.state &= ~kIgnoredModifiers; 593 uint16 ch = GetCharacterFromXEvent(reinterpret_cast<XEvent*>(©)); 594 return ch ? ch : GetCharacterFromKeyCode(key_code_, flags() & EF_SHIFT_DOWN); 595#elif defined(USE_OZONE) 596 return is_char() ? key_code_ : GetCharacterFromKeyCode( 597 key_code_, flags() & EF_SHIFT_DOWN); 598#else 599 NOTIMPLEMENTED(); 600 return 0; 601#endif 602} 603 604KeyEvent* KeyEvent::Copy() const { 605#if defined(USE_OZONE) 606 KeyEvent* copy = new KeyEvent(*this); 607#else 608 KeyEvent* copy = new KeyEvent(::CopyNativeEvent(native_event()), is_char()); 609#endif 610#if defined(USE_X11) 611 copy->set_delete_native_event(true); 612#endif 613 return copy; 614} 615 616bool KeyEvent::IsUnicodeKeyCode() const { 617 if (!IsAltDown()) 618 return false; 619 const int key = key_code(); 620 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9) 621 return true; 622 // Check whether the user is using the numeric keypad with num-lock off. 623 // In that case, EF_EXTENDED will not be set; if it is set, the key event 624 // originated from the relevant non-numpad dedicated key, e.g. [Insert]. 625 return (!(flags() & EF_EXTENDED) && 626 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN || 627 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR || 628 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP || 629 key == VKEY_PRIOR)); 630} 631 632void KeyEvent::NormalizeFlags() { 633 int mask = 0; 634 switch (key_code()) { 635 case VKEY_CONTROL: 636 mask = EF_CONTROL_DOWN; 637 break; 638 case VKEY_SHIFT: 639 mask = EF_SHIFT_DOWN; 640 break; 641 case VKEY_MENU: 642 mask = EF_ALT_DOWN; 643 break; 644 case VKEY_CAPITAL: 645 mask = EF_CAPS_LOCK_DOWN; 646 break; 647 default: 648 return; 649 } 650 if (type() == ET_KEY_PRESSED) 651 set_flags(flags() | mask); 652 else 653 set_flags(flags() & ~mask); 654} 655 656//////////////////////////////////////////////////////////////////////////////// 657// TranslatedKeyEvent 658 659TranslatedKeyEvent::TranslatedKeyEvent(const base::NativeEvent& native_event, 660 bool is_char) 661 : KeyEvent(native_event, is_char) { 662 SetType(type() == ET_KEY_PRESSED ? 663 ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE); 664} 665 666TranslatedKeyEvent::TranslatedKeyEvent(bool is_press, 667 KeyboardCode key_code, 668 int flags) 669 : KeyEvent((is_press ? ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE), 670 key_code, 671 flags, 672 false) { 673} 674 675void TranslatedKeyEvent::ConvertToKeyEvent() { 676 SetType(type() == ET_TRANSLATED_KEY_PRESS ? 677 ET_KEY_PRESSED : ET_KEY_RELEASED); 678} 679 680//////////////////////////////////////////////////////////////////////////////// 681// ScrollEvent 682 683ScrollEvent::ScrollEvent(const base::NativeEvent& native_event) 684 : MouseEvent(native_event) { 685 if (type() == ET_SCROLL) { 686 GetScrollOffsets(native_event, 687 &x_offset_, &y_offset_, 688 &x_offset_ordinal_, &y_offset_ordinal_, 689 &finger_count_); 690 } else if (type() == ET_SCROLL_FLING_START || 691 type() == ET_SCROLL_FLING_CANCEL) { 692 GetFlingData(native_event, 693 &x_offset_, &y_offset_, 694 &x_offset_ordinal_, &y_offset_ordinal_, 695 NULL); 696 } else { 697 NOTREACHED() << "Unexpected event type " << type() 698 << " when constructing a ScrollEvent."; 699 } 700} 701 702ScrollEvent::ScrollEvent(EventType type, 703 const gfx::Point& location, 704 base::TimeDelta time_stamp, 705 int flags, 706 float x_offset, 707 float y_offset, 708 float x_offset_ordinal, 709 float y_offset_ordinal, 710 int finger_count) 711 : MouseEvent(type, location, location, flags), 712 x_offset_(x_offset), 713 y_offset_(y_offset), 714 x_offset_ordinal_(x_offset_ordinal), 715 y_offset_ordinal_(y_offset_ordinal), 716 finger_count_(finger_count) { 717 set_time_stamp(time_stamp); 718 CHECK(IsScrollEvent()); 719} 720 721void ScrollEvent::Scale(const float factor) { 722 x_offset_ *= factor; 723 y_offset_ *= factor; 724 x_offset_ordinal_ *= factor; 725 y_offset_ordinal_ *= factor; 726} 727 728void ScrollEvent::UpdateForRootTransform( 729 const gfx::Transform& inverted_root_transform) { 730 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 731 gfx::DecomposedTransform decomp; 732 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 733 DCHECK(success); 734 if (decomp.scale[0]) 735 x_offset_ordinal_ *= decomp.scale[0]; 736 if (decomp.scale[1]) 737 y_offset_ordinal_ *= decomp.scale[1]; 738} 739 740//////////////////////////////////////////////////////////////////////////////// 741// GestureEvent 742 743GestureEvent::GestureEvent(EventType type, 744 int x, 745 int y, 746 int flags, 747 base::TimeDelta time_stamp, 748 const GestureEventDetails& details, 749 unsigned int touch_ids_bitfield) 750 : LocatedEvent(type, 751 gfx::Point(x, y), 752 gfx::Point(x, y), 753 time_stamp, 754 flags | EF_FROM_TOUCH), 755 details_(details), 756 touch_ids_bitfield_(touch_ids_bitfield) { 757} 758 759GestureEvent::~GestureEvent() { 760} 761 762int GestureEvent::GetLowestTouchId() const { 763 if (touch_ids_bitfield_ == 0) 764 return -1; 765 int i = -1; 766 // Find the index of the least significant 1 bit 767 while (!(1 << ++i & touch_ids_bitfield_)); 768 return i; 769} 770 771} // namespace ui 772