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 #include <X11/keysym.h> 11 #endif 12 13 #include <cmath> 14 #include <cstring> 15 16 #include "base/metrics/histogram.h" 17 #include "base/strings/stringprintf.h" 18 #include "ui/events/event_utils.h" 19 #include "ui/events/keycodes/keyboard_code_conversion.h" 20 #include "ui/gfx/point3_f.h" 21 #include "ui/gfx/point_conversions.h" 22 #include "ui/gfx/transform.h" 23 #include "ui/gfx/transform_util.h" 24 25 #if defined(USE_X11) 26 #include "ui/events/keycodes/keyboard_code_conversion_x.h" 27 #elif defined(USE_OZONE) 28 #include "ui/events/keycodes/keyboard_code_conversion.h" 29 #endif 30 31 namespace { 32 33 std::string EventTypeName(ui::EventType type) { 34 #define RETURN_IF_TYPE(t) if (type == ui::t) return #t 35 #define CASE_TYPE(t) case ui::t: return #t 36 switch (type) { 37 CASE_TYPE(ET_UNKNOWN); 38 CASE_TYPE(ET_MOUSE_PRESSED); 39 CASE_TYPE(ET_MOUSE_DRAGGED); 40 CASE_TYPE(ET_MOUSE_RELEASED); 41 CASE_TYPE(ET_MOUSE_MOVED); 42 CASE_TYPE(ET_MOUSE_ENTERED); 43 CASE_TYPE(ET_MOUSE_EXITED); 44 CASE_TYPE(ET_KEY_PRESSED); 45 CASE_TYPE(ET_KEY_RELEASED); 46 CASE_TYPE(ET_MOUSEWHEEL); 47 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED); 48 CASE_TYPE(ET_TOUCH_RELEASED); 49 CASE_TYPE(ET_TOUCH_PRESSED); 50 CASE_TYPE(ET_TOUCH_MOVED); 51 CASE_TYPE(ET_TOUCH_CANCELLED); 52 CASE_TYPE(ET_DROP_TARGET_EVENT); 53 CASE_TYPE(ET_TRANSLATED_KEY_PRESS); 54 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE); 55 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN); 56 CASE_TYPE(ET_GESTURE_SCROLL_END); 57 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE); 58 CASE_TYPE(ET_GESTURE_SHOW_PRESS); 59 CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE); 60 CASE_TYPE(ET_GESTURE_TAP); 61 CASE_TYPE(ET_GESTURE_TAP_DOWN); 62 CASE_TYPE(ET_GESTURE_TAP_CANCEL); 63 CASE_TYPE(ET_GESTURE_BEGIN); 64 CASE_TYPE(ET_GESTURE_END); 65 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP); 66 CASE_TYPE(ET_GESTURE_PINCH_BEGIN); 67 CASE_TYPE(ET_GESTURE_PINCH_END); 68 CASE_TYPE(ET_GESTURE_PINCH_UPDATE); 69 CASE_TYPE(ET_GESTURE_LONG_PRESS); 70 CASE_TYPE(ET_GESTURE_LONG_TAP); 71 CASE_TYPE(ET_GESTURE_SWIPE); 72 CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED); 73 CASE_TYPE(ET_GESTURE_DOUBLE_TAP); 74 CASE_TYPE(ET_SCROLL); 75 CASE_TYPE(ET_SCROLL_FLING_START); 76 CASE_TYPE(ET_SCROLL_FLING_CANCEL); 77 CASE_TYPE(ET_CANCEL_MODE); 78 CASE_TYPE(ET_UMA_DATA); 79 case ui::ET_LAST: NOTREACHED(); return std::string(); 80 // Don't include default, so that we get an error when new type is added. 81 } 82 #undef CASE_TYPE 83 84 NOTREACHED(); 85 return std::string(); 86 } 87 88 bool IsX11SendEventTrue(const base::NativeEvent& event) { 89 #if defined(USE_X11) 90 return event && event->xany.send_event; 91 #else 92 return false; 93 #endif 94 } 95 96 bool X11EventHasNonStandardState(const base::NativeEvent& event) { 97 #if defined(USE_X11) 98 const unsigned int kAllStateMask = 99 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask | 100 Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | 101 LockMask | ControlMask | AnyModifier; 102 return event && (event->xkey.state & ~kAllStateMask) != 0; 103 #else 104 return false; 105 #endif 106 } 107 108 } // namespace 109 110 namespace ui { 111 112 //////////////////////////////////////////////////////////////////////////////// 113 // Event 114 115 // static 116 scoped_ptr<Event> Event::Clone(const Event& event) { 117 if (event.IsKeyEvent()) { 118 return scoped_ptr<Event>(new KeyEvent(static_cast<const KeyEvent&>(event))); 119 } 120 121 if (event.IsMouseEvent()) { 122 if (event.IsMouseWheelEvent()) { 123 return scoped_ptr<Event>( 124 new MouseWheelEvent(static_cast<const MouseWheelEvent&>(event))); 125 } 126 127 return scoped_ptr<Event>( 128 new MouseEvent(static_cast<const MouseEvent&>(event))); 129 } 130 131 if (event.IsTouchEvent()) { 132 return scoped_ptr<Event>( 133 new TouchEvent(static_cast<const TouchEvent&>(event))); 134 } 135 136 if (event.IsGestureEvent()) { 137 return scoped_ptr<Event>( 138 new GestureEvent(static_cast<const GestureEvent&>(event))); 139 } 140 141 if (event.IsScrollEvent()) { 142 return scoped_ptr<Event>( 143 new ScrollEvent(static_cast<const ScrollEvent&>(event))); 144 } 145 146 return scoped_ptr<Event>(new Event(event)); 147 } 148 149 Event::~Event() { 150 if (delete_native_event_) 151 ReleaseCopiedNativeEvent(native_event_); 152 } 153 154 GestureEvent* Event::AsGestureEvent() { 155 CHECK(IsGestureEvent()); 156 return static_cast<GestureEvent*>(this); 157 } 158 159 const GestureEvent* Event::AsGestureEvent() const { 160 CHECK(IsGestureEvent()); 161 return static_cast<const GestureEvent*>(this); 162 } 163 164 bool Event::HasNativeEvent() const { 165 base::NativeEvent null_event; 166 std::memset(&null_event, 0, sizeof(null_event)); 167 return !!std::memcmp(&native_event_, &null_event, sizeof(null_event)); 168 } 169 170 void Event::StopPropagation() { 171 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch 172 // events. 173 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH); 174 CHECK(cancelable_); 175 result_ = static_cast<EventResult>(result_ | ER_CONSUMED); 176 } 177 178 void Event::SetHandled() { 179 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch 180 // events. 181 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH); 182 CHECK(cancelable_); 183 result_ = static_cast<EventResult>(result_ | ER_HANDLED); 184 } 185 186 Event::Event(EventType type, base::TimeDelta time_stamp, int flags) 187 : type_(type), 188 time_stamp_(time_stamp), 189 flags_(flags), 190 native_event_(base::NativeEvent()), 191 delete_native_event_(false), 192 cancelable_(true), 193 target_(NULL), 194 phase_(EP_PREDISPATCH), 195 result_(ER_UNHANDLED), 196 source_device_id_(ED_UNKNOWN_DEVICE) { 197 if (type_ < ET_LAST) 198 name_ = EventTypeName(type_); 199 } 200 201 Event::Event(const base::NativeEvent& native_event, 202 EventType type, 203 int flags) 204 : type_(type), 205 time_stamp_(EventTimeFromNative(native_event)), 206 flags_(flags), 207 native_event_(native_event), 208 delete_native_event_(false), 209 cancelable_(true), 210 target_(NULL), 211 phase_(EP_PREDISPATCH), 212 result_(ER_UNHANDLED), 213 source_device_id_(ED_UNKNOWN_DEVICE) { 214 base::TimeDelta delta = EventTimeForNow() - time_stamp_; 215 if (type_ < ET_LAST) 216 name_ = EventTypeName(type_); 217 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", 218 delta.InMicroseconds(), 1, 1000000, 100); 219 std::string name_for_event = 220 base::StringPrintf("Event.Latency.Browser.%s", name_.c_str()); 221 base::HistogramBase* counter_for_type = 222 base::Histogram::FactoryGet( 223 name_for_event, 224 1, 225 1000000, 226 100, 227 base::HistogramBase::kUmaTargetedHistogramFlag); 228 counter_for_type->Add(delta.InMicroseconds()); 229 230 #if defined(USE_X11) 231 if (native_event->type == GenericEvent) { 232 XIDeviceEvent* xiev = 233 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 234 source_device_id_ = xiev->sourceid; 235 } 236 #endif 237 } 238 239 Event::Event(const Event& copy) 240 : type_(copy.type_), 241 time_stamp_(copy.time_stamp_), 242 latency_(copy.latency_), 243 flags_(copy.flags_), 244 native_event_(CopyNativeEvent(copy.native_event_)), 245 delete_native_event_(true), 246 cancelable_(true), 247 target_(NULL), 248 phase_(EP_PREDISPATCH), 249 result_(ER_UNHANDLED), 250 source_device_id_(copy.source_device_id_) { 251 if (type_ < ET_LAST) 252 name_ = EventTypeName(type_); 253 } 254 255 void Event::SetType(EventType type) { 256 if (type_ < ET_LAST) 257 name_ = std::string(); 258 type_ = type; 259 if (type_ < ET_LAST) 260 name_ = EventTypeName(type_); 261 } 262 263 //////////////////////////////////////////////////////////////////////////////// 264 // CancelModeEvent 265 266 CancelModeEvent::CancelModeEvent() 267 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) { 268 set_cancelable(false); 269 } 270 271 CancelModeEvent::~CancelModeEvent() { 272 } 273 274 //////////////////////////////////////////////////////////////////////////////// 275 // LocatedEvent 276 277 LocatedEvent::~LocatedEvent() { 278 } 279 280 LocatedEvent::LocatedEvent(const base::NativeEvent& native_event) 281 : Event(native_event, 282 EventTypeFromNative(native_event), 283 EventFlagsFromNative(native_event)), 284 location_(EventLocationFromNative(native_event)), 285 root_location_(location_) { 286 } 287 288 LocatedEvent::LocatedEvent(EventType type, 289 const gfx::PointF& location, 290 const gfx::PointF& root_location, 291 base::TimeDelta time_stamp, 292 int flags) 293 : Event(type, time_stamp, flags), 294 location_(location), 295 root_location_(root_location) { 296 } 297 298 void LocatedEvent::UpdateForRootTransform( 299 const gfx::Transform& reversed_root_transform) { 300 // Transform has to be done at root level. 301 gfx::Point3F p(location_); 302 reversed_root_transform.TransformPoint(&p); 303 location_ = p.AsPointF(); 304 root_location_ = location_; 305 } 306 307 //////////////////////////////////////////////////////////////////////////////// 308 // MouseEvent 309 310 MouseEvent::MouseEvent(const base::NativeEvent& native_event) 311 : LocatedEvent(native_event), 312 changed_button_flags_( 313 GetChangedMouseButtonFlagsFromNative(native_event)) { 314 if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED) 315 SetClickCount(GetRepeatCount(*this)); 316 } 317 318 MouseEvent::MouseEvent(EventType type, 319 const gfx::PointF& location, 320 const gfx::PointF& root_location, 321 int flags, 322 int changed_button_flags) 323 : LocatedEvent(type, location, root_location, EventTimeForNow(), flags), 324 changed_button_flags_(changed_button_flags) { 325 if (this->type() == ET_MOUSE_MOVED && IsAnyButton()) 326 SetType(ET_MOUSE_DRAGGED); 327 } 328 329 // static 330 bool MouseEvent::IsRepeatedClickEvent( 331 const MouseEvent& event1, 332 const MouseEvent& event2) { 333 // These values match the Windows defaults. 334 static const int kDoubleClickTimeMS = 500; 335 static const int kDoubleClickWidth = 4; 336 static const int kDoubleClickHeight = 4; 337 338 if (event1.type() != ET_MOUSE_PRESSED || 339 event2.type() != ET_MOUSE_PRESSED) 340 return false; 341 342 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks. 343 if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) != 344 (event2.flags() & ~EF_IS_DOUBLE_CLICK)) 345 return false; 346 347 base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp(); 348 349 if (time_difference.InMilliseconds() > kDoubleClickTimeMS) 350 return false; 351 352 if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2) 353 return false; 354 355 if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2) 356 return false; 357 358 return true; 359 } 360 361 // static 362 int MouseEvent::GetRepeatCount(const MouseEvent& event) { 363 int click_count = 1; 364 if (last_click_event_) { 365 if (event.type() == ui::ET_MOUSE_RELEASED) { 366 if (event.changed_button_flags() == 367 last_click_event_->changed_button_flags()) { 368 last_click_complete_ = true; 369 return last_click_event_->GetClickCount(); 370 } else { 371 // If last_click_event_ has changed since this button was pressed 372 // return a click count of 1. 373 return click_count; 374 } 375 } 376 if (event.time_stamp() != last_click_event_->time_stamp()) 377 last_click_complete_ = true; 378 if (!last_click_complete_ || 379 IsX11SendEventTrue(event.native_event())) { 380 click_count = last_click_event_->GetClickCount(); 381 } else if (IsRepeatedClickEvent(*last_click_event_, event)) { 382 click_count = last_click_event_->GetClickCount() + 1; 383 } 384 delete last_click_event_; 385 } 386 last_click_event_ = new MouseEvent(event); 387 last_click_complete_ = false; 388 if (click_count > 3) 389 click_count = 3; 390 last_click_event_->SetClickCount(click_count); 391 return click_count; 392 } 393 394 void MouseEvent::ResetLastClickForTest() { 395 if (last_click_event_) { 396 delete last_click_event_; 397 last_click_event_ = NULL; 398 last_click_complete_ = false; 399 } 400 } 401 402 // static 403 MouseEvent* MouseEvent::last_click_event_ = NULL; 404 bool MouseEvent::last_click_complete_ = false; 405 406 int MouseEvent::GetClickCount() const { 407 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 408 return 0; 409 410 if (flags() & EF_IS_TRIPLE_CLICK) 411 return 3; 412 else if (flags() & EF_IS_DOUBLE_CLICK) 413 return 2; 414 else 415 return 1; 416 } 417 418 void MouseEvent::SetClickCount(int click_count) { 419 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 420 return; 421 422 DCHECK(click_count > 0); 423 DCHECK(click_count <= 3); 424 425 int f = flags(); 426 switch (click_count) { 427 case 1: 428 f &= ~EF_IS_DOUBLE_CLICK; 429 f &= ~EF_IS_TRIPLE_CLICK; 430 break; 431 case 2: 432 f |= EF_IS_DOUBLE_CLICK; 433 f &= ~EF_IS_TRIPLE_CLICK; 434 break; 435 case 3: 436 f &= ~EF_IS_DOUBLE_CLICK; 437 f |= EF_IS_TRIPLE_CLICK; 438 break; 439 } 440 set_flags(f); 441 } 442 443 //////////////////////////////////////////////////////////////////////////////// 444 // MouseWheelEvent 445 446 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event) 447 : MouseEvent(native_event), 448 offset_(GetMouseWheelOffset(native_event)) { 449 } 450 451 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event) 452 : MouseEvent(scroll_event), 453 offset_(scroll_event.x_offset(), scroll_event.y_offset()){ 454 SetType(ET_MOUSEWHEEL); 455 } 456 457 MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event, 458 int x_offset, 459 int y_offset) 460 : MouseEvent(mouse_event), offset_(x_offset, y_offset) { 461 DCHECK(type() == ET_MOUSEWHEEL); 462 } 463 464 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event) 465 : MouseEvent(mouse_wheel_event), 466 offset_(mouse_wheel_event.offset()) { 467 DCHECK(type() == ET_MOUSEWHEEL); 468 } 469 470 MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset, 471 const gfx::PointF& location, 472 const gfx::PointF& root_location, 473 int flags, 474 int changed_button_flags) 475 : MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, flags, 476 changed_button_flags), 477 offset_(offset) { 478 } 479 480 #if defined(OS_WIN) 481 // This value matches windows WHEEL_DELTA. 482 // static 483 const int MouseWheelEvent::kWheelDelta = 120; 484 #else 485 // This value matches GTK+ wheel scroll amount. 486 const int MouseWheelEvent::kWheelDelta = 53; 487 #endif 488 489 void MouseWheelEvent::UpdateForRootTransform( 490 const gfx::Transform& inverted_root_transform) { 491 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 492 gfx::DecomposedTransform decomp; 493 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 494 DCHECK(success); 495 if (decomp.scale[0]) 496 offset_.set_x(offset_.x() * decomp.scale[0]); 497 if (decomp.scale[1]) 498 offset_.set_y(offset_.y() * decomp.scale[1]); 499 } 500 501 //////////////////////////////////////////////////////////////////////////////// 502 // TouchEvent 503 504 TouchEvent::TouchEvent(const base::NativeEvent& native_event) 505 : LocatedEvent(native_event), 506 touch_id_(GetTouchId(native_event)), 507 radius_x_(GetTouchRadiusX(native_event)), 508 radius_y_(GetTouchRadiusY(native_event)), 509 rotation_angle_(GetTouchAngle(native_event)), 510 force_(GetTouchForce(native_event)) { 511 latency()->AddLatencyNumberWithTimestamp( 512 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 513 0, 514 0, 515 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 516 1); 517 518 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 519 520 if (type() == ET_TOUCH_PRESSED) 521 IncrementTouchIdRefCount(native_event); 522 } 523 524 TouchEvent::TouchEvent(EventType type, 525 const gfx::PointF& location, 526 int touch_id, 527 base::TimeDelta time_stamp) 528 : LocatedEvent(type, location, location, time_stamp, 0), 529 touch_id_(touch_id), 530 radius_x_(0.0f), 531 radius_y_(0.0f), 532 rotation_angle_(0.0f), 533 force_(0.0f) { 534 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 535 } 536 537 TouchEvent::TouchEvent(EventType type, 538 const gfx::PointF& location, 539 int flags, 540 int touch_id, 541 base::TimeDelta time_stamp, 542 float radius_x, 543 float radius_y, 544 float angle, 545 float force) 546 : LocatedEvent(type, location, location, time_stamp, flags), 547 touch_id_(touch_id), 548 radius_x_(radius_x), 549 radius_y_(radius_y), 550 rotation_angle_(angle), 551 force_(force) { 552 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 553 } 554 555 TouchEvent::~TouchEvent() { 556 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11 557 // platform setups the tracking_id to slot mapping. So in dtor here, 558 // if this touch event is a release event, we clear the mapping accordingly. 559 if (HasNativeEvent()) 560 ClearTouchIdIfReleased(native_event()); 561 } 562 563 void TouchEvent::UpdateForRootTransform( 564 const gfx::Transform& inverted_root_transform) { 565 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 566 gfx::DecomposedTransform decomp; 567 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 568 DCHECK(success); 569 if (decomp.scale[0]) 570 radius_x_ *= decomp.scale[0]; 571 if (decomp.scale[1]) 572 radius_y_ *= decomp.scale[1]; 573 } 574 575 //////////////////////////////////////////////////////////////////////////////// 576 // KeyEvent 577 578 // static 579 KeyEvent* KeyEvent::last_key_event_ = NULL; 580 581 // static 582 bool KeyEvent::IsRepeated(const KeyEvent& event) { 583 // A safe guard in case if there were continous key pressed events that are 584 // not auto repeat. 585 const int kMaxAutoRepeatTimeMs = 2000; 586 // Ignore key events that have non standard state masks as it may be 587 // reposted by an IME. IBUS-GTK uses this field to detect the 588 // re-posted event for example. crbug.com/385873. 589 if (X11EventHasNonStandardState(event.native_event())) 590 return false; 591 if (event.is_char()) 592 return false; 593 if (event.type() == ui::ET_KEY_RELEASED) { 594 delete last_key_event_; 595 last_key_event_ = NULL; 596 return false; 597 } 598 CHECK_EQ(ui::ET_KEY_PRESSED, event.type()); 599 if (!last_key_event_) { 600 last_key_event_ = new KeyEvent(event); 601 return false; 602 } 603 if (event.key_code() == last_key_event_->key_code() && 604 event.flags() == last_key_event_->flags() && 605 (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() < 606 kMaxAutoRepeatTimeMs) { 607 return true; 608 } 609 delete last_key_event_; 610 last_key_event_ = new KeyEvent(event); 611 return false; 612 } 613 614 KeyEvent::KeyEvent(const base::NativeEvent& native_event) 615 : Event(native_event, 616 EventTypeFromNative(native_event), 617 EventFlagsFromNative(native_event)), 618 key_code_(KeyboardCodeFromNative(native_event)), 619 code_(CodeFromNative(native_event)), 620 is_char_(IsCharFromNative(native_event)), 621 platform_keycode_(PlatformKeycodeFromNative(native_event)), 622 character_(0) { 623 if (IsRepeated(*this)) 624 set_flags(flags() | ui::EF_IS_REPEAT); 625 626 #if defined(USE_X11) 627 NormalizeFlags(); 628 #endif 629 #if defined(OS_WIN) 630 // Only Windows has native character events. 631 if (is_char_) 632 character_ = native_event.wParam; 633 #endif 634 } 635 636 KeyEvent::KeyEvent(EventType type, 637 KeyboardCode key_code, 638 int flags) 639 : Event(type, EventTimeForNow(), flags), 640 key_code_(key_code), 641 is_char_(false), 642 platform_keycode_(0), 643 character_() { 644 } 645 646 KeyEvent::KeyEvent(EventType type, 647 KeyboardCode key_code, 648 const std::string& code, 649 int flags) 650 : Event(type, EventTimeForNow(), flags), 651 key_code_(key_code), 652 code_(code), 653 is_char_(false), 654 platform_keycode_(0), 655 character_(0) { 656 } 657 658 KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags) 659 : Event(ET_KEY_PRESSED, EventTimeForNow(), flags), 660 key_code_(key_code), 661 code_(""), 662 is_char_(true), 663 platform_keycode_(0), 664 character_(character) { 665 } 666 667 KeyEvent::KeyEvent(const KeyEvent& rhs) 668 : Event(rhs), 669 key_code_(rhs.key_code_), 670 code_(rhs.code_), 671 is_char_(rhs.is_char_), 672 platform_keycode_(rhs.platform_keycode_), 673 character_(rhs.character_) { 674 if (rhs.extended_key_event_data_) 675 extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone()); 676 } 677 678 KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) { 679 if (this != &rhs) { 680 Event::operator=(rhs); 681 key_code_ = rhs.key_code_; 682 code_ = rhs.code_; 683 is_char_ = rhs.is_char_; 684 platform_keycode_ = rhs.platform_keycode_; 685 character_ = rhs.character_; 686 687 if (rhs.extended_key_event_data_) 688 extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone()); 689 } 690 return *this; 691 } 692 693 KeyEvent::~KeyEvent() {} 694 695 void KeyEvent::SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data) { 696 extended_key_event_data_ = data.Pass(); 697 } 698 699 base::char16 KeyEvent::GetCharacter() const { 700 if (is_char_ || character_) 701 return character_; 702 703 // TODO(kpschoedel): streamline these cases after settling Ozone 704 // positional coding. 705 #if defined(OS_WIN) 706 // Native Windows character events always have is_char_ == true, 707 // so this is a synthetic or native keystroke event. 708 character_ = GetCharacterFromKeyCode(key_code_, flags()); 709 return character_; 710 #elif defined(USE_X11) 711 if (!native_event()) { 712 character_ = GetCharacterFromKeyCode(key_code_, flags()); 713 return character_; 714 } 715 716 DCHECK(native_event()->type == KeyPress || 717 native_event()->type == KeyRelease || 718 (native_event()->type == GenericEvent && 719 (native_event()->xgeneric.evtype == XI_KeyPress || 720 native_event()->xgeneric.evtype == XI_KeyRelease))); 721 722 // When a control key is held, prefer ASCII characters to non ASCII 723 // characters in order to use it for shortcut keys. GetCharacterFromKeyCode 724 // returns 'a' for VKEY_A even if the key is actually bound to '' in X11. 725 // GetCharacterFromXEvent returns '' in that case. 726 return IsControlDown() ? 727 GetCharacterFromKeyCode(key_code_, flags()) : 728 GetCharacterFromXEvent(native_event()); 729 #else 730 if (native_event()) { 731 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED || 732 EventTypeFromNative(native_event()) == ET_KEY_RELEASED); 733 } 734 735 return GetCharacterFromKeyCode(key_code_, flags()); 736 #endif 737 } 738 739 base::char16 KeyEvent::GetText() const { 740 if ((flags() & EF_CONTROL_DOWN) != 0) { 741 return GetControlCharacterForKeycode(key_code_, 742 (flags() & EF_SHIFT_DOWN) != 0); 743 } 744 return GetUnmodifiedText(); 745 } 746 747 base::char16 KeyEvent::GetUnmodifiedText() const { 748 if (!is_char_ && (key_code_ == VKEY_RETURN)) 749 return '\r'; 750 return GetCharacter(); 751 } 752 753 bool KeyEvent::IsUnicodeKeyCode() const { 754 #if defined(OS_WIN) 755 if (!IsAltDown()) 756 return false; 757 const int key = key_code(); 758 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9) 759 return true; 760 // Check whether the user is using the numeric keypad with num-lock off. 761 // In that case, EF_EXTENDED will not be set; if it is set, the key event 762 // originated from the relevant non-numpad dedicated key, e.g. [Insert]. 763 return (!(flags() & EF_EXTENDED) && 764 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN || 765 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR || 766 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP || 767 key == VKEY_PRIOR)); 768 #else 769 return false; 770 #endif 771 } 772 773 void KeyEvent::NormalizeFlags() { 774 int mask = 0; 775 switch (key_code()) { 776 case VKEY_CONTROL: 777 mask = EF_CONTROL_DOWN; 778 break; 779 case VKEY_SHIFT: 780 mask = EF_SHIFT_DOWN; 781 break; 782 case VKEY_MENU: 783 mask = EF_ALT_DOWN; 784 break; 785 case VKEY_CAPITAL: 786 mask = EF_CAPS_LOCK_DOWN; 787 break; 788 default: 789 return; 790 } 791 if (type() == ET_KEY_PRESSED) 792 set_flags(flags() | mask); 793 else 794 set_flags(flags() & ~mask); 795 } 796 797 bool KeyEvent::IsTranslated() const { 798 switch (type()) { 799 case ET_KEY_PRESSED: 800 case ET_KEY_RELEASED: 801 return false; 802 case ET_TRANSLATED_KEY_PRESS: 803 case ET_TRANSLATED_KEY_RELEASE: 804 return true; 805 default: 806 NOTREACHED(); 807 return false; 808 } 809 } 810 811 void KeyEvent::SetTranslated(bool translated) { 812 switch (type()) { 813 case ET_KEY_PRESSED: 814 case ET_TRANSLATED_KEY_PRESS: 815 SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED); 816 break; 817 case ET_KEY_RELEASED: 818 case ET_TRANSLATED_KEY_RELEASE: 819 SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED); 820 break; 821 default: 822 NOTREACHED(); 823 } 824 } 825 826 bool KeyEvent::IsRightSideKey() const { 827 switch (key_code_) { 828 case VKEY_CONTROL: 829 case VKEY_SHIFT: 830 case VKEY_MENU: 831 case VKEY_LWIN: 832 #if defined(USE_X11) 833 // Under X11, setting code_ requires platform-dependent information, and 834 // currently assumes that X keycodes are based on Linux evdev keycodes. 835 // In certain test environments this is not the case, and code_ is not 836 // set accurately, so we need a different mechanism. Fortunately X11 key 837 // mapping preserves the left-right distinction, so testing keysyms works 838 // if the value is available (as it is for all X11 native-based events). 839 if (platform_keycode_) { 840 return (platform_keycode_ == XK_Shift_R) || 841 (platform_keycode_ == XK_Control_R) || 842 (platform_keycode_ == XK_Alt_R) || 843 (platform_keycode_ == XK_Meta_R) || 844 (platform_keycode_ == XK_Super_R) || 845 (platform_keycode_ == XK_Hyper_R); 846 } 847 // Fall through to the generic code if we have no platform_keycode_. 848 // Under X11, this must be a synthetic event, so we can require that 849 // code_ be set correctly. 850 #endif 851 return ((code_.size() > 5) && 852 (code_.compare(code_.size() - 5, 5, "Right", 5)) == 0); 853 default: 854 return false; 855 } 856 } 857 858 KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const { 859 switch (key_code_) { 860 case VKEY_SHIFT: 861 return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT; 862 case VKEY_CONTROL: 863 return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL; 864 case VKEY_MENU: 865 return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU; 866 case VKEY_LWIN: 867 return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN; 868 // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this 869 // function is only called on X11. Likely the tests here will be replaced 870 // with a DOM-based code enumeration test in the course of Ozone 871 // platform-indpendent key event work. 872 case VKEY_0: 873 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0; 874 case VKEY_1: 875 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1; 876 case VKEY_2: 877 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2; 878 case VKEY_3: 879 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3; 880 case VKEY_4: 881 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4; 882 case VKEY_5: 883 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5; 884 case VKEY_6: 885 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6; 886 case VKEY_7: 887 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7; 888 case VKEY_8: 889 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8; 890 case VKEY_9: 891 return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9; 892 default: 893 return key_code_; 894 } 895 } 896 897 uint16 KeyEvent::GetConflatedWindowsKeyCode() const { 898 if (is_char_) 899 return character_; 900 return key_code_; 901 } 902 903 //////////////////////////////////////////////////////////////////////////////// 904 // ScrollEvent 905 906 ScrollEvent::ScrollEvent(const base::NativeEvent& native_event) 907 : MouseEvent(native_event) { 908 if (type() == ET_SCROLL) { 909 GetScrollOffsets(native_event, 910 &x_offset_, &y_offset_, 911 &x_offset_ordinal_, &y_offset_ordinal_, 912 &finger_count_); 913 } else if (type() == ET_SCROLL_FLING_START || 914 type() == ET_SCROLL_FLING_CANCEL) { 915 GetFlingData(native_event, 916 &x_offset_, &y_offset_, 917 &x_offset_ordinal_, &y_offset_ordinal_, 918 NULL); 919 } else { 920 NOTREACHED() << "Unexpected event type " << type() 921 << " when constructing a ScrollEvent."; 922 } 923 } 924 925 ScrollEvent::ScrollEvent(EventType type, 926 const gfx::PointF& location, 927 base::TimeDelta time_stamp, 928 int flags, 929 float x_offset, 930 float y_offset, 931 float x_offset_ordinal, 932 float y_offset_ordinal, 933 int finger_count) 934 : MouseEvent(type, location, location, flags, 0), 935 x_offset_(x_offset), 936 y_offset_(y_offset), 937 x_offset_ordinal_(x_offset_ordinal), 938 y_offset_ordinal_(y_offset_ordinal), 939 finger_count_(finger_count) { 940 set_time_stamp(time_stamp); 941 CHECK(IsScrollEvent()); 942 } 943 944 void ScrollEvent::Scale(const float factor) { 945 x_offset_ *= factor; 946 y_offset_ *= factor; 947 x_offset_ordinal_ *= factor; 948 y_offset_ordinal_ *= factor; 949 } 950 951 //////////////////////////////////////////////////////////////////////////////// 952 // GestureEvent 953 954 GestureEvent::GestureEvent(float x, 955 float y, 956 int flags, 957 base::TimeDelta time_stamp, 958 const GestureEventDetails& details) 959 : LocatedEvent(details.type(), 960 gfx::PointF(x, y), 961 gfx::PointF(x, y), 962 time_stamp, 963 flags | EF_FROM_TOUCH), 964 details_(details) { 965 } 966 967 GestureEvent::~GestureEvent() { 968 } 969 970 } // namespace ui 971