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