event.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 30namespace { 31 32std::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 87bool 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 95bool 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 109namespace ui { 110 111//////////////////////////////////////////////////////////////////////////////// 112// Event 113 114Event::~Event() { 115 if (delete_native_event_) 116 ReleaseCopiedNativeEvent(native_event_); 117} 118 119GestureEvent* Event::AsGestureEvent() { 120 CHECK(IsGestureEvent()); 121 return static_cast<GestureEvent*>(this); 122} 123 124const GestureEvent* Event::AsGestureEvent() const { 125 CHECK(IsGestureEvent()); 126 return static_cast<const GestureEvent*>(this); 127} 128 129bool Event::HasNativeEvent() const { 130 base::NativeEvent null_event; 131 std::memset(&null_event, 0, sizeof(null_event)); 132 return !!std::memcmp(&native_event_, &null_event, sizeof(null_event)); 133} 134 135void Event::StopPropagation() { 136 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch 137 // events. 138 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH); 139 CHECK(cancelable_); 140 result_ = static_cast<EventResult>(result_ | ER_CONSUMED); 141} 142 143void Event::SetHandled() { 144 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch 145 // events. 146 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH); 147 CHECK(cancelable_); 148 result_ = static_cast<EventResult>(result_ | ER_HANDLED); 149} 150 151Event::Event(EventType type, base::TimeDelta time_stamp, int flags) 152 : type_(type), 153 time_stamp_(time_stamp), 154 flags_(flags), 155 native_event_(base::NativeEvent()), 156 delete_native_event_(false), 157 cancelable_(true), 158 target_(NULL), 159 phase_(EP_PREDISPATCH), 160 result_(ER_UNHANDLED), 161 source_device_id_(ED_UNKNOWN_DEVICE) { 162 if (type_ < ET_LAST) 163 name_ = EventTypeName(type_); 164} 165 166Event::Event(const base::NativeEvent& native_event, 167 EventType type, 168 int flags) 169 : type_(type), 170 time_stamp_(EventTimeFromNative(native_event)), 171 flags_(flags), 172 native_event_(native_event), 173 delete_native_event_(false), 174 cancelable_(true), 175 target_(NULL), 176 phase_(EP_PREDISPATCH), 177 result_(ER_UNHANDLED), 178 source_device_id_(ED_UNKNOWN_DEVICE) { 179 base::TimeDelta delta = EventTimeForNow() - time_stamp_; 180 if (type_ < ET_LAST) 181 name_ = EventTypeName(type_); 182 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", 183 delta.InMicroseconds(), 1, 1000000, 100); 184 std::string name_for_event = 185 base::StringPrintf("Event.Latency.Browser.%s", name_.c_str()); 186 base::HistogramBase* counter_for_type = 187 base::Histogram::FactoryGet( 188 name_for_event, 189 1, 190 1000000, 191 100, 192 base::HistogramBase::kUmaTargetedHistogramFlag); 193 counter_for_type->Add(delta.InMicroseconds()); 194 195#if defined(USE_X11) 196 if (native_event->type == GenericEvent) { 197 XIDeviceEvent* xiev = 198 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 199 source_device_id_ = xiev->deviceid; 200 } 201#endif 202} 203 204Event::Event(const Event& copy) 205 : type_(copy.type_), 206 time_stamp_(copy.time_stamp_), 207 latency_(copy.latency_), 208 flags_(copy.flags_), 209 native_event_(CopyNativeEvent(copy.native_event_)), 210 delete_native_event_(true), 211 cancelable_(true), 212 target_(NULL), 213 phase_(EP_PREDISPATCH), 214 result_(ER_UNHANDLED), 215 source_device_id_(copy.source_device_id_) { 216 if (type_ < ET_LAST) 217 name_ = EventTypeName(type_); 218} 219 220void Event::SetType(EventType type) { 221 if (type_ < ET_LAST) 222 name_ = std::string(); 223 type_ = type; 224 if (type_ < ET_LAST) 225 name_ = EventTypeName(type_); 226} 227 228//////////////////////////////////////////////////////////////////////////////// 229// CancelModeEvent 230 231CancelModeEvent::CancelModeEvent() 232 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) { 233 set_cancelable(false); 234} 235 236CancelModeEvent::~CancelModeEvent() { 237} 238 239//////////////////////////////////////////////////////////////////////////////// 240// LocatedEvent 241 242LocatedEvent::~LocatedEvent() { 243} 244 245LocatedEvent::LocatedEvent(const base::NativeEvent& native_event) 246 : Event(native_event, 247 EventTypeFromNative(native_event), 248 EventFlagsFromNative(native_event)), 249 location_(EventLocationFromNative(native_event)), 250 root_location_(location_) { 251} 252 253LocatedEvent::LocatedEvent(EventType type, 254 const gfx::PointF& location, 255 const gfx::PointF& root_location, 256 base::TimeDelta time_stamp, 257 int flags) 258 : Event(type, time_stamp, flags), 259 location_(location), 260 root_location_(root_location) { 261} 262 263void LocatedEvent::UpdateForRootTransform( 264 const gfx::Transform& reversed_root_transform) { 265 // Transform has to be done at root level. 266 gfx::Point3F p(location_); 267 reversed_root_transform.TransformPoint(&p); 268 location_ = p.AsPointF(); 269 root_location_ = location_; 270} 271 272//////////////////////////////////////////////////////////////////////////////// 273// MouseEvent 274 275MouseEvent::MouseEvent(const base::NativeEvent& native_event) 276 : LocatedEvent(native_event), 277 changed_button_flags_( 278 GetChangedMouseButtonFlagsFromNative(native_event)) { 279 if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED) 280 SetClickCount(GetRepeatCount(*this)); 281} 282 283MouseEvent::MouseEvent(EventType type, 284 const gfx::PointF& location, 285 const gfx::PointF& root_location, 286 int flags, 287 int changed_button_flags) 288 : LocatedEvent(type, location, root_location, EventTimeForNow(), flags), 289 changed_button_flags_(changed_button_flags) { 290 if (this->type() == ET_MOUSE_MOVED && IsAnyButton()) 291 SetType(ET_MOUSE_DRAGGED); 292} 293 294// static 295bool MouseEvent::IsRepeatedClickEvent( 296 const MouseEvent& event1, 297 const MouseEvent& event2) { 298 // These values match the Windows defaults. 299 static const int kDoubleClickTimeMS = 500; 300 static const int kDoubleClickWidth = 4; 301 static const int kDoubleClickHeight = 4; 302 303 if (event1.type() != ET_MOUSE_PRESSED || 304 event2.type() != ET_MOUSE_PRESSED) 305 return false; 306 307 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks. 308 if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) != 309 (event2.flags() & ~EF_IS_DOUBLE_CLICK)) 310 return false; 311 312 base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp(); 313 314 if (time_difference.InMilliseconds() > kDoubleClickTimeMS) 315 return false; 316 317 if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2) 318 return false; 319 320 if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2) 321 return false; 322 323 return true; 324} 325 326// static 327int MouseEvent::GetRepeatCount(const MouseEvent& event) { 328 int click_count = 1; 329 if (last_click_event_) { 330 if (event.type() == ui::ET_MOUSE_RELEASED) 331 return last_click_event_->GetClickCount(); 332 if (IsX11SendEventTrue(event.native_event())) 333 click_count = last_click_event_->GetClickCount(); 334 else if (IsRepeatedClickEvent(*last_click_event_, event)) 335 click_count = last_click_event_->GetClickCount() + 1; 336 delete last_click_event_; 337 } 338 last_click_event_ = new MouseEvent(event); 339 if (click_count > 3) 340 click_count = 3; 341 last_click_event_->SetClickCount(click_count); 342 return click_count; 343} 344 345// static 346MouseEvent* MouseEvent::last_click_event_ = NULL; 347 348int MouseEvent::GetClickCount() const { 349 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 350 return 0; 351 352 if (flags() & EF_IS_TRIPLE_CLICK) 353 return 3; 354 else if (flags() & EF_IS_DOUBLE_CLICK) 355 return 2; 356 else 357 return 1; 358} 359 360void MouseEvent::SetClickCount(int click_count) { 361 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED) 362 return; 363 364 DCHECK(click_count > 0); 365 DCHECK(click_count <= 3); 366 367 int f = flags(); 368 switch (click_count) { 369 case 1: 370 f &= ~EF_IS_DOUBLE_CLICK; 371 f &= ~EF_IS_TRIPLE_CLICK; 372 break; 373 case 2: 374 f |= EF_IS_DOUBLE_CLICK; 375 f &= ~EF_IS_TRIPLE_CLICK; 376 break; 377 case 3: 378 f &= ~EF_IS_DOUBLE_CLICK; 379 f |= EF_IS_TRIPLE_CLICK; 380 break; 381 } 382 set_flags(f); 383} 384 385//////////////////////////////////////////////////////////////////////////////// 386// MouseWheelEvent 387 388MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event) 389 : MouseEvent(native_event), 390 offset_(GetMouseWheelOffset(native_event)) { 391} 392 393MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event) 394 : MouseEvent(scroll_event), 395 offset_(scroll_event.x_offset(), scroll_event.y_offset()){ 396 SetType(ET_MOUSEWHEEL); 397} 398 399MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event, 400 int x_offset, 401 int y_offset) 402 : MouseEvent(mouse_event), offset_(x_offset, y_offset) { 403 DCHECK(type() == ET_MOUSEWHEEL); 404} 405 406MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event) 407 : MouseEvent(mouse_wheel_event), 408 offset_(mouse_wheel_event.offset()) { 409 DCHECK(type() == ET_MOUSEWHEEL); 410} 411 412MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset, 413 const gfx::PointF& location, 414 const gfx::PointF& root_location, 415 int flags, 416 int changed_button_flags) 417 : MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, flags, 418 changed_button_flags), 419 offset_(offset) { 420} 421 422#if defined(OS_WIN) 423// This value matches windows WHEEL_DELTA. 424// static 425const int MouseWheelEvent::kWheelDelta = 120; 426#else 427// This value matches GTK+ wheel scroll amount. 428const int MouseWheelEvent::kWheelDelta = 53; 429#endif 430 431void MouseWheelEvent::UpdateForRootTransform( 432 const gfx::Transform& inverted_root_transform) { 433 LocatedEvent::UpdateForRootTransform(inverted_root_transform); 434 gfx::DecomposedTransform decomp; 435 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform); 436 DCHECK(success); 437 if (decomp.scale[0]) 438 offset_.set_x(offset_.x() * decomp.scale[0]); 439 if (decomp.scale[1]) 440 offset_.set_y(offset_.y() * decomp.scale[1]); 441} 442 443//////////////////////////////////////////////////////////////////////////////// 444// TouchEvent 445 446TouchEvent::TouchEvent(const base::NativeEvent& native_event) 447 : LocatedEvent(native_event), 448 touch_id_(GetTouchId(native_event)), 449 radius_x_(GetTouchRadiusX(native_event)), 450 radius_y_(GetTouchRadiusY(native_event)), 451 rotation_angle_(GetTouchAngle(native_event)), 452 force_(GetTouchForce(native_event)) { 453 latency()->AddLatencyNumberWithTimestamp( 454 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 455 0, 456 0, 457 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 458 1); 459 460 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 461} 462 463TouchEvent::TouchEvent(EventType type, 464 const gfx::PointF& location, 465 int touch_id, 466 base::TimeDelta time_stamp) 467 : LocatedEvent(type, location, location, time_stamp, 0), 468 touch_id_(touch_id), 469 radius_x_(0.0f), 470 radius_y_(0.0f), 471 rotation_angle_(0.0f), 472 force_(0.0f) { 473 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 474} 475 476TouchEvent::TouchEvent(EventType type, 477 const gfx::PointF& location, 478 int flags, 479 int touch_id, 480 base::TimeDelta time_stamp, 481 float radius_x, 482 float radius_y, 483 float angle, 484 float force) 485 : LocatedEvent(type, location, location, time_stamp, flags), 486 touch_id_(touch_id), 487 radius_x_(radius_x), 488 radius_y_(radius_y), 489 rotation_angle_(angle), 490 force_(force) { 491 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); 492} 493 494TouchEvent::~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 502void 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 518KeyEvent* KeyEvent::last_key_event_ = NULL; 519 520// static 521bool 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 553KeyEvent::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 570KeyEvent::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 581KeyEvent::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 594uint16 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 (native_event()->type == GenericEvent && 608 (native_event()->xgeneric.evtype == XI_KeyPress || 609 native_event()->xgeneric.evtype == XI_KeyRelease))); 610 611 // When a control key is held, prefer ASCII characters to non ASCII 612 // characters in order to use it for shortcut keys. GetCharacterFromKeyCode 613 // returns 'a' for VKEY_A even if the key is actually bound to 'à' in X11. 614 // GetCharacterFromXEvent returns 'à' in that case. 615 return IsControlDown() ? 616 GetCharacterFromKeyCode(key_code_, flags()) : 617 GetCharacterFromXEvent(native_event()); 618#else 619 if (native_event()) { 620 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED || 621 EventTypeFromNative(native_event()) == ET_KEY_RELEASED); 622 } 623 624 return GetCharacterFromKeyCode(key_code_, flags()); 625#endif 626} 627 628bool KeyEvent::IsUnicodeKeyCode() const { 629#if defined(OS_WIN) 630 if (!IsAltDown()) 631 return false; 632 const int key = key_code(); 633 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9) 634 return true; 635 // Check whether the user is using the numeric keypad with num-lock off. 636 // In that case, EF_EXTENDED will not be set; if it is set, the key event 637 // originated from the relevant non-numpad dedicated key, e.g. [Insert]. 638 return (!(flags() & EF_EXTENDED) && 639 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN || 640 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR || 641 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP || 642 key == VKEY_PRIOR)); 643#else 644 return false; 645#endif 646} 647 648void KeyEvent::NormalizeFlags() { 649 int mask = 0; 650 switch (key_code()) { 651 case VKEY_CONTROL: 652 mask = EF_CONTROL_DOWN; 653 break; 654 case VKEY_SHIFT: 655 mask = EF_SHIFT_DOWN; 656 break; 657 case VKEY_MENU: 658 mask = EF_ALT_DOWN; 659 break; 660 case VKEY_CAPITAL: 661 mask = EF_CAPS_LOCK_DOWN; 662 break; 663 default: 664 return; 665 } 666 if (type() == ET_KEY_PRESSED) 667 set_flags(flags() | mask); 668 else 669 set_flags(flags() & ~mask); 670} 671 672bool KeyEvent::IsTranslated() const { 673 switch (type()) { 674 case ET_KEY_PRESSED: 675 case ET_KEY_RELEASED: 676 return false; 677 case ET_TRANSLATED_KEY_PRESS: 678 case ET_TRANSLATED_KEY_RELEASE: 679 return true; 680 default: 681 NOTREACHED(); 682 return false; 683 } 684} 685 686void KeyEvent::SetTranslated(bool translated) { 687 switch (type()) { 688 case ET_KEY_PRESSED: 689 case ET_TRANSLATED_KEY_PRESS: 690 SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED); 691 break; 692 case ET_KEY_RELEASED: 693 case ET_TRANSLATED_KEY_RELEASE: 694 SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED); 695 break; 696 default: 697 NOTREACHED(); 698 } 699} 700 701//////////////////////////////////////////////////////////////////////////////// 702// ScrollEvent 703 704ScrollEvent::ScrollEvent(const base::NativeEvent& native_event) 705 : MouseEvent(native_event) { 706 if (type() == ET_SCROLL) { 707 GetScrollOffsets(native_event, 708 &x_offset_, &y_offset_, 709 &x_offset_ordinal_, &y_offset_ordinal_, 710 &finger_count_); 711 } else if (type() == ET_SCROLL_FLING_START || 712 type() == ET_SCROLL_FLING_CANCEL) { 713 GetFlingData(native_event, 714 &x_offset_, &y_offset_, 715 &x_offset_ordinal_, &y_offset_ordinal_, 716 NULL); 717 } else { 718 NOTREACHED() << "Unexpected event type " << type() 719 << " when constructing a ScrollEvent."; 720 } 721} 722 723ScrollEvent::ScrollEvent(EventType type, 724 const gfx::PointF& location, 725 base::TimeDelta time_stamp, 726 int flags, 727 float x_offset, 728 float y_offset, 729 float x_offset_ordinal, 730 float y_offset_ordinal, 731 int finger_count) 732 : MouseEvent(type, location, location, flags, 0), 733 x_offset_(x_offset), 734 y_offset_(y_offset), 735 x_offset_ordinal_(x_offset_ordinal), 736 y_offset_ordinal_(y_offset_ordinal), 737 finger_count_(finger_count) { 738 set_time_stamp(time_stamp); 739 CHECK(IsScrollEvent()); 740} 741 742void ScrollEvent::Scale(const float factor) { 743 x_offset_ *= factor; 744 y_offset_ *= factor; 745 x_offset_ordinal_ *= factor; 746 y_offset_ordinal_ *= factor; 747} 748 749//////////////////////////////////////////////////////////////////////////////// 750// GestureEvent 751 752GestureEvent::GestureEvent(float x, 753 float y, 754 int flags, 755 base::TimeDelta time_stamp, 756 const GestureEventDetails& details) 757 : LocatedEvent(details.type(), 758 gfx::PointF(x, y), 759 gfx::PointF(x, y), 760 time_stamp, 761 flags | EF_FROM_TOUCH), 762 details_(details) { 763} 764 765GestureEvent::~GestureEvent() { 766} 767 768} // namespace ui 769