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 #ifndef UI_EVENTS_EVENT_H_ 6 #define UI_EVENTS_EVENT_H_ 7 8 #include "base/basictypes.h" 9 #include "base/compiler_specific.h" 10 #include "base/event_types.h" 11 #include "base/logging.h" 12 #include "base/time/time.h" 13 #include "ui/events/event_constants.h" 14 #include "ui/events/gestures/gesture_types.h" 15 #include "ui/events/keycodes/keyboard_codes.h" 16 #include "ui/events/latency_info.h" 17 #include "ui/gfx/point.h" 18 19 namespace gfx { 20 class Transform; 21 } 22 23 namespace ui { 24 class EventTarget; 25 26 class EVENTS_EXPORT Event { 27 public: 28 virtual ~Event(); 29 30 class DispatcherApi { 31 public: 32 explicit DispatcherApi(Event* event) : event_(event) {} 33 34 void set_target(EventTarget* target) { 35 event_->target_ = target; 36 } 37 38 void set_phase(EventPhase phase) { event_->phase_ = phase; } 39 void set_result(int result) { 40 event_->result_ = static_cast<EventResult>(result); 41 } 42 43 private: 44 DispatcherApi(); 45 Event* event_; 46 47 DISALLOW_COPY_AND_ASSIGN(DispatcherApi); 48 }; 49 50 const base::NativeEvent& native_event() const { return native_event_; } 51 EventType type() const { return type_; } 52 const std::string& name() const { return name_; } 53 // time_stamp represents time since machine was booted. 54 const base::TimeDelta& time_stamp() const { return time_stamp_; } 55 int flags() const { return flags_; } 56 57 // This is only intended to be used externally by classes that are modifying 58 // events in EventFilter::PreHandleKeyEvent(). 59 void set_flags(int flags) { flags_ = flags; } 60 61 EventTarget* target() const { return target_; } 62 EventPhase phase() const { return phase_; } 63 EventResult result() const { return result_; } 64 65 LatencyInfo* latency() { return &latency_; } 66 const LatencyInfo* latency() const { return &latency_; } 67 void set_latency(const LatencyInfo& latency) { latency_ = latency; } 68 69 // By default, events are "cancelable", this means any default processing that 70 // the containing abstraction layer may perform can be prevented by calling 71 // SetHandled(). SetHandled() or StopPropagation() must not be called for 72 // events that are not cancelable. 73 bool cancelable() const { return cancelable_; } 74 75 // The following methods return true if the respective keys were pressed at 76 // the time the event was created. 77 bool IsShiftDown() const { return (flags_ & EF_SHIFT_DOWN) != 0; } 78 bool IsControlDown() const { return (flags_ & EF_CONTROL_DOWN) != 0; } 79 bool IsCapsLockDown() const { return (flags_ & EF_CAPS_LOCK_DOWN) != 0; } 80 bool IsAltDown() const { return (flags_ & EF_ALT_DOWN) != 0; } 81 bool IsAltGrDown() const { return (flags_ & EF_ALTGR_DOWN) != 0; } 82 83 bool IsKeyEvent() const { 84 return type_ == ET_KEY_PRESSED || 85 type_ == ET_KEY_RELEASED || 86 type_ == ET_TRANSLATED_KEY_PRESS || 87 type_ == ET_TRANSLATED_KEY_RELEASE; 88 } 89 90 bool IsMouseEvent() const { 91 return type_ == ET_MOUSE_PRESSED || 92 type_ == ET_MOUSE_DRAGGED || 93 type_ == ET_MOUSE_RELEASED || 94 type_ == ET_MOUSE_MOVED || 95 type_ == ET_MOUSE_ENTERED || 96 type_ == ET_MOUSE_EXITED || 97 type_ == ET_MOUSEWHEEL || 98 type_ == ET_MOUSE_CAPTURE_CHANGED; 99 } 100 101 bool IsTouchEvent() const { 102 return type_ == ET_TOUCH_RELEASED || 103 type_ == ET_TOUCH_PRESSED || 104 type_ == ET_TOUCH_MOVED || 105 type_ == ET_TOUCH_STATIONARY || 106 type_ == ET_TOUCH_CANCELLED; 107 } 108 109 bool IsGestureEvent() const { 110 switch (type_) { 111 case ET_GESTURE_SCROLL_BEGIN: 112 case ET_GESTURE_SCROLL_END: 113 case ET_GESTURE_SCROLL_UPDATE: 114 case ET_GESTURE_TAP: 115 case ET_GESTURE_TAP_CANCEL: 116 case ET_GESTURE_TAP_DOWN: 117 case ET_GESTURE_BEGIN: 118 case ET_GESTURE_END: 119 case ET_GESTURE_TWO_FINGER_TAP: 120 case ET_GESTURE_PINCH_BEGIN: 121 case ET_GESTURE_PINCH_END: 122 case ET_GESTURE_PINCH_UPDATE: 123 case ET_GESTURE_LONG_PRESS: 124 case ET_GESTURE_LONG_TAP: 125 case ET_GESTURE_MULTIFINGER_SWIPE: 126 case ET_GESTURE_SHOW_PRESS: 127 // When adding a gesture event which is paired with an event which 128 // occurs earlier, add the event to |IsEndingEvent|. 129 return true; 130 131 case ET_SCROLL_FLING_CANCEL: 132 case ET_SCROLL_FLING_START: 133 // These can be ScrollEvents too. EF_FROM_TOUCH determines if they're 134 // Gesture or Scroll events. 135 return (flags_ & EF_FROM_TOUCH) == EF_FROM_TOUCH; 136 137 default: 138 break; 139 } 140 return false; 141 } 142 143 // An ending event is paired with the event which started it. Setting capture 144 // should not prevent ending events from getting to their initial target. 145 bool IsEndingEvent() const { 146 switch(type_) { 147 case ui::ET_TOUCH_CANCELLED: 148 case ui::ET_GESTURE_TAP_CANCEL: 149 case ui::ET_GESTURE_END: 150 case ui::ET_GESTURE_SCROLL_END: 151 case ui::ET_GESTURE_PINCH_END: 152 return true; 153 default: 154 return false; 155 } 156 } 157 158 bool IsScrollEvent() const { 159 // Flings can be GestureEvents too. EF_FROM_TOUCH determins if they're 160 // Gesture or Scroll events. 161 return type_ == ET_SCROLL || 162 ((type_ == ET_SCROLL_FLING_START || 163 type_ == ET_SCROLL_FLING_CANCEL) && 164 !(flags() & EF_FROM_TOUCH)); 165 } 166 167 bool IsScrollGestureEvent() const { 168 return type_ == ET_GESTURE_SCROLL_BEGIN || 169 type_ == ET_GESTURE_SCROLL_UPDATE || 170 type_ == ET_GESTURE_SCROLL_END; 171 } 172 173 bool IsFlingScrollEvent() const { 174 return type_ == ET_SCROLL_FLING_CANCEL || 175 type_ == ET_SCROLL_FLING_START; 176 } 177 178 bool IsMouseWheelEvent() const { 179 return type_ == ET_MOUSEWHEEL; 180 } 181 182 // Returns true if the event has a valid |native_event_|. 183 bool HasNativeEvent() const; 184 185 // Immediately stops the propagation of the event. This must be called only 186 // from an EventHandler during an event-dispatch. Any event handler that may 187 // be in the list will not receive the event after this is called. 188 // Note that StopPropagation() can be called only for cancelable events. 189 void StopPropagation(); 190 bool stopped_propagation() const { return !!(result_ & ER_CONSUMED); } 191 192 // Marks the event as having been handled. A handled event does not reach the 193 // next event phase. For example, if an event is handled during the pre-target 194 // phase, then the event is dispatched to all pre-target handlers, but not to 195 // the target or post-target handlers. 196 // Note that SetHandled() can be called only for cancelable events. 197 void SetHandled(); 198 bool handled() const { return result_ != ER_UNHANDLED; } 199 200 protected: 201 Event(EventType type, base::TimeDelta time_stamp, int flags); 202 Event(const base::NativeEvent& native_event, EventType type, int flags); 203 Event(const Event& copy); 204 void SetType(EventType type); 205 void set_delete_native_event(bool delete_native_event) { 206 delete_native_event_ = delete_native_event; 207 } 208 void set_cancelable(bool cancelable) { cancelable_ = cancelable; } 209 210 void set_time_stamp(const base::TimeDelta& time_stamp) { 211 time_stamp_ = time_stamp; 212 } 213 214 void set_name(const std::string& name) { name_ = name; } 215 216 private: 217 friend class EventTestApi; 218 219 // Safely initializes the native event members of this class. 220 void Init(); 221 void InitWithNativeEvent(const base::NativeEvent& native_event); 222 223 EventType type_; 224 std::string name_; 225 base::TimeDelta time_stamp_; 226 LatencyInfo latency_; 227 int flags_; 228 base::NativeEvent native_event_; 229 bool delete_native_event_; 230 bool cancelable_; 231 EventTarget* target_; 232 EventPhase phase_; 233 EventResult result_; 234 }; 235 236 class EVENTS_EXPORT CancelModeEvent : public Event { 237 public: 238 CancelModeEvent(); 239 virtual ~CancelModeEvent(); 240 }; 241 242 class EVENTS_EXPORT LocatedEvent : public Event { 243 public: 244 virtual ~LocatedEvent(); 245 246 int x() const { return location_.x(); } 247 int y() const { return location_.y(); } 248 void set_location(const gfx::Point& location) { location_ = location; } 249 gfx::Point location() const { return location_; } 250 void set_root_location(const gfx::Point& root_location) { 251 root_location_ = root_location; 252 } 253 gfx::Point root_location() const { return root_location_; } 254 255 // Transform the locations using |inverted_root_transform|. 256 // This is applied to both |location_| and |root_location_|. 257 virtual void UpdateForRootTransform( 258 const gfx::Transform& inverted_root_transform); 259 260 template <class T> void ConvertLocationToTarget(T* source, T* target) { 261 if (target && target != source) 262 T::ConvertPointToTarget(source, target, &location_); 263 } 264 265 protected: 266 friend class LocatedEventTestApi; 267 explicit LocatedEvent(const base::NativeEvent& native_event); 268 269 // Create a new LocatedEvent which is identical to the provided model. 270 // If source / target windows are provided, the model location will be 271 // converted from |source| coordinate system to |target| coordinate system. 272 template <class T> 273 LocatedEvent(const LocatedEvent& model, T* source, T* target) 274 : Event(model), 275 location_(model.location_), 276 root_location_(model.root_location_) { 277 ConvertLocationToTarget(source, target); 278 } 279 280 // Used for synthetic events in testing. 281 LocatedEvent(EventType type, 282 const gfx::Point& location, 283 const gfx::Point& root_location, 284 base::TimeDelta time_stamp, 285 int flags); 286 287 gfx::Point location_; 288 289 // |location_| multiplied by an optional transformation matrix for 290 // rotations, animations and skews. 291 gfx::Point root_location_; 292 }; 293 294 class EVENTS_EXPORT MouseEvent : public LocatedEvent { 295 public: 296 explicit MouseEvent(const base::NativeEvent& native_event); 297 298 // Create a new MouseEvent based on the provided model. 299 // Uses the provided |type| and |flags| for the new event. 300 // If source / target windows are provided, the model location will be 301 // converted from |source| coordinate system to |target| coordinate system. 302 template <class T> 303 MouseEvent(const MouseEvent& model, T* source, T* target) 304 : LocatedEvent(model, source, target), 305 changed_button_flags_(model.changed_button_flags_) { 306 } 307 308 template <class T> 309 MouseEvent(const MouseEvent& model, 310 T* source, 311 T* target, 312 EventType type, 313 int flags) 314 : LocatedEvent(model, source, target), 315 changed_button_flags_(model.changed_button_flags_) { 316 SetType(type); 317 set_flags(flags); 318 } 319 320 // Used for synthetic events in testing and by the gesture recognizer. 321 MouseEvent(EventType type, 322 const gfx::Point& location, 323 const gfx::Point& root_location, 324 int flags); 325 326 // Conveniences to quickly test what button is down 327 bool IsOnlyLeftMouseButton() const { 328 return (flags() & EF_LEFT_MOUSE_BUTTON) && 329 !(flags() & (EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON)); 330 } 331 332 bool IsLeftMouseButton() const { 333 return (flags() & EF_LEFT_MOUSE_BUTTON) != 0; 334 } 335 336 bool IsOnlyMiddleMouseButton() const { 337 return (flags() & EF_MIDDLE_MOUSE_BUTTON) && 338 !(flags() & (EF_LEFT_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON)); 339 } 340 341 bool IsMiddleMouseButton() const { 342 return (flags() & EF_MIDDLE_MOUSE_BUTTON) != 0; 343 } 344 345 bool IsOnlyRightMouseButton() const { 346 return (flags() & EF_RIGHT_MOUSE_BUTTON) && 347 !(flags() & (EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON)); 348 } 349 350 bool IsRightMouseButton() const { 351 return (flags() & EF_RIGHT_MOUSE_BUTTON) != 0; 352 } 353 354 bool IsAnyButton() const { 355 return (flags() & (EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON | 356 EF_RIGHT_MOUSE_BUTTON)) != 0; 357 } 358 359 // Compares two mouse down events and returns true if the second one should 360 // be considered a repeat of the first. 361 static bool IsRepeatedClickEvent( 362 const MouseEvent& event1, 363 const MouseEvent& event2); 364 365 // Get the click count. Can be 1, 2 or 3 for mousedown messages, 0 otherwise. 366 int GetClickCount() const; 367 368 // Set the click count for a mousedown message. Can be 1, 2 or 3. 369 void SetClickCount(int click_count); 370 371 // Identifies the button that changed. During a press this corresponds to the 372 // button that was pressed and during a release this corresponds to the button 373 // that was released. 374 // NOTE: during a press and release flags() contains the complete set of 375 // flags. Use this to determine the button that was pressed or released. 376 int changed_button_flags() const { return changed_button_flags_; } 377 378 private: 379 // Returns the repeat count based on the previous mouse click, if it is 380 // recent enough and within a small enough distance. 381 static int GetRepeatCount(const MouseEvent& click_event); 382 383 // See description above getter for details. 384 int changed_button_flags_; 385 386 static MouseEvent* last_click_event_; 387 }; 388 389 class ScrollEvent; 390 391 class EVENTS_EXPORT MouseWheelEvent : public MouseEvent { 392 public: 393 // See |offset| for details. 394 static const int kWheelDelta; 395 396 explicit MouseWheelEvent(const base::NativeEvent& native_event); 397 explicit MouseWheelEvent(const ScrollEvent& scroll_event); 398 MouseWheelEvent(const MouseEvent& mouse_event, int x_offset, int y_offset); 399 MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event); 400 401 template <class T> 402 MouseWheelEvent(const MouseWheelEvent& model, 403 T* source, 404 T* target, 405 EventType type, 406 int flags) 407 : MouseEvent(model, source, target, type, flags), 408 offset_(model.x_offset(), model.y_offset()){ 409 } 410 411 // The amount to scroll. This is in multiples of kWheelDelta. 412 // Note: x_offset() > 0/y_offset() > 0 means scroll left/up. 413 int x_offset() const { return offset_.x(); } 414 int y_offset() const { return offset_.y(); } 415 const gfx::Vector2d& offset() const { return offset_; } 416 417 // Overridden from LocatedEvent. 418 virtual void UpdateForRootTransform( 419 const gfx::Transform& inverted_root_transform) OVERRIDE; 420 421 private: 422 gfx::Vector2d offset_; 423 }; 424 425 class EVENTS_EXPORT TouchEvent : public LocatedEvent { 426 public: 427 explicit TouchEvent(const base::NativeEvent& native_event); 428 429 // Create a new TouchEvent which is identical to the provided model. 430 // If source / target windows are provided, the model location will be 431 // converted from |source| coordinate system to |target| coordinate system. 432 template <class T> 433 TouchEvent(const TouchEvent& model, T* source, T* target) 434 : LocatedEvent(model, source, target), 435 touch_id_(model.touch_id_), 436 radius_x_(model.radius_x_), 437 radius_y_(model.radius_y_), 438 rotation_angle_(model.rotation_angle_), 439 force_(model.force_) { 440 } 441 442 TouchEvent(EventType type, 443 const gfx::Point& root_location, 444 int touch_id, 445 base::TimeDelta time_stamp); 446 447 TouchEvent(EventType type, 448 const gfx::Point& location, 449 int flags, 450 int touch_id, 451 base::TimeDelta timestamp, 452 float radius_x, 453 float radius_y, 454 float angle, 455 float force); 456 457 virtual ~TouchEvent(); 458 459 int touch_id() const { return touch_id_; } 460 float radius_x() const { return radius_x_; } 461 float radius_y() const { return radius_y_; } 462 float rotation_angle() const { return rotation_angle_; } 463 float force() const { return force_; } 464 465 // Relocate the touch-point to a new |origin|. 466 // This is useful when touch event is in X Root Window coordinates, 467 // and it needs to be mapped into Aura Root Window coordinates. 468 void Relocate(const gfx::Point& origin); 469 470 // Used for unit tests. 471 void set_radius_x(const float r) { radius_x_ = r; } 472 void set_radius_y(const float r) { radius_y_ = r; } 473 474 // Overridden from LocatedEvent. 475 virtual void UpdateForRootTransform( 476 const gfx::Transform& inverted_root_transform) OVERRIDE; 477 478 protected: 479 void set_radius(float radius_x, float radius_y) { 480 radius_x_ = radius_x; 481 radius_y_ = radius_y; 482 } 483 484 void set_rotation_angle(float rotation_angle) { 485 rotation_angle_ = rotation_angle; 486 } 487 488 void set_force(float force) { force_ = force; } 489 490 private: 491 // The identity (typically finger) of the touch starting at 0 and incrementing 492 // for each separable additional touch that the hardware can detect. 493 const int touch_id_; 494 495 // Radius of the X (major) axis of the touch ellipse. 0.0 if unknown. 496 float radius_x_; 497 498 // Radius of the Y (minor) axis of the touch ellipse. 0.0 if unknown. 499 float radius_y_; 500 501 // Angle of the major axis away from the X axis. Default 0.0. 502 float rotation_angle_; 503 504 // Force (pressure) of the touch. Normalized to be [0, 1]. Default to be 0.0. 505 float force_; 506 }; 507 508 class EVENTS_EXPORT KeyEvent : public Event { 509 public: 510 KeyEvent(const base::NativeEvent& native_event, bool is_char); 511 512 // Used for synthetic events. 513 KeyEvent(EventType type, KeyboardCode key_code, int flags, bool is_char); 514 515 // Used for synthetic events with code of DOM KeyboardEvent (e.g. 'KeyA') 516 // See also: ui/events/keycodes/dom4/keycode_converter_data.h 517 KeyEvent(EventType type, KeyboardCode key_code, const std::string& code, 518 int flags, bool is_char); 519 520 // This allows an I18N virtual keyboard to fabricate a keyboard event that 521 // does not have a corresponding KeyboardCode (example: U+00E1 Latin small 522 // letter A with acute, U+0410 Cyrillic capital letter A). 523 void set_character(uint16 character) { character_ = character; } 524 525 // Gets the character generated by this key event. It only supports Unicode 526 // BMP characters. 527 uint16 GetCharacter() const; 528 529 KeyboardCode key_code() const { return key_code_; } 530 bool is_char() const { return is_char_; } 531 532 // This is only intended to be used externally by classes that are modifying 533 // events in EventFilter::PreHandleKeyEvent(). set_character() should also be 534 // called. 535 void set_key_code(KeyboardCode key_code) { key_code_ = key_code; } 536 537 // Returns true for [Alt]+<num-pad digit> Unicode alt key codes used by Win. 538 // TODO(msw): Additional work may be needed for analogues on other platforms. 539 bool IsUnicodeKeyCode() const; 540 541 std::string code() const { return code_; } 542 543 // Normalizes flags_ to make it Windows/Mac compatible. Since the way 544 // of setting modifier mask on X is very different than Windows/Mac as shown 545 // in http://crbug.com/127142#c8, the normalization is necessary. 546 void NormalizeFlags(); 547 548 private: 549 KeyboardCode key_code_; 550 551 // String of 'code' defined in DOM KeyboardEvent (e.g. 'KeyA', 'Space') 552 // http://www.w3.org/TR/uievents/#keyboard-key-codes. 553 // 554 // This value represents the physical position in the keyboard and can be 555 // converted from / to keyboard scan code like XKB. 556 std::string code_; 557 558 // True if this is a translated character event (vs. a raw key down). Both 559 // share the same type: ET_KEY_PRESSED. 560 bool is_char_; 561 562 uint16 character_; 563 }; 564 565 // A key event which is translated by an input method (IME). 566 // For example, if an IME receives a KeyEvent(VKEY_SPACE), and it does not 567 // consume the key, the IME usually generates and dispatches a 568 // TranslatedKeyEvent(VKEY_SPACE) event. If the IME receives a KeyEvent and 569 // it does consume the event, it might dispatch a 570 // TranslatedKeyEvent(VKEY_PROCESSKEY) event as defined in the DOM spec. 571 class EVENTS_EXPORT TranslatedKeyEvent : public KeyEvent { 572 public: 573 TranslatedKeyEvent(const base::NativeEvent& native_event, bool is_char); 574 575 // Used for synthetic events such as a VKEY_PROCESSKEY key event. 576 TranslatedKeyEvent(bool is_press, KeyboardCode key_code, int flags); 577 578 // Changes the type() of the object from ET_TRANSLATED_KEY_* to ET_KEY_* so 579 // that RenderWidgetHostViewAura and NativeWidgetAura could handle the event. 580 void ConvertToKeyEvent(); 581 582 private: 583 DISALLOW_COPY_AND_ASSIGN(TranslatedKeyEvent); 584 }; 585 586 class EVENTS_EXPORT ScrollEvent : public MouseEvent { 587 public: 588 explicit ScrollEvent(const base::NativeEvent& native_event); 589 template <class T> 590 ScrollEvent(const ScrollEvent& model, 591 T* source, 592 T* target) 593 : MouseEvent(model, source, target), 594 x_offset_(model.x_offset_), 595 y_offset_(model.y_offset_), 596 x_offset_ordinal_(model.x_offset_ordinal_), 597 y_offset_ordinal_(model.y_offset_ordinal_), 598 finger_count_(model.finger_count_){ 599 } 600 601 // Used for tests. 602 ScrollEvent(EventType type, 603 const gfx::Point& location, 604 base::TimeDelta time_stamp, 605 int flags, 606 float x_offset, 607 float y_offset, 608 float x_offset_ordinal, 609 float y_offset_ordinal, 610 int finger_count); 611 612 // Scale the scroll event's offset value. 613 // This is useful in the multi-monitor setup where it needs to be scaled 614 // to provide a consistent user experience. 615 void Scale(const float factor); 616 617 float x_offset() const { return x_offset_; } 618 float y_offset() const { return y_offset_; } 619 float x_offset_ordinal() const { return x_offset_ordinal_; } 620 float y_offset_ordinal() const { return y_offset_ordinal_; } 621 int finger_count() const { return finger_count_; } 622 623 private: 624 // Potential accelerated offsets. 625 float x_offset_; 626 float y_offset_; 627 // Unaccelerated offsets. 628 float x_offset_ordinal_; 629 float y_offset_ordinal_; 630 // Number of fingers on the pad. 631 int finger_count_; 632 }; 633 634 class EVENTS_EXPORT GestureEvent : public LocatedEvent { 635 public: 636 GestureEvent(EventType type, 637 int x, 638 int y, 639 int flags, 640 base::TimeDelta time_stamp, 641 const GestureEventDetails& details, 642 unsigned int touch_ids_bitfield); 643 644 // Create a new GestureEvent which is identical to the provided model. 645 // If source / target windows are provided, the model location will be 646 // converted from |source| coordinate system to |target| coordinate system. 647 template <typename T> 648 GestureEvent(const GestureEvent& model, T* source, T* target) 649 : LocatedEvent(model, source, target), 650 details_(model.details_), 651 touch_ids_bitfield_(model.touch_ids_bitfield_) { 652 } 653 654 virtual ~GestureEvent(); 655 656 const GestureEventDetails& details() const { return details_; } 657 658 // Returns the lowest touch-id of any of the touches which make up this 659 // gesture. If there are no touches associated with this gesture, returns -1. 660 int GetLowestTouchId() const; 661 662 private: 663 GestureEventDetails details_; 664 665 // The set of indices of ones in the binary representation of 666 // touch_ids_bitfield_ is the set of touch_ids associate with this gesture. 667 // This value is stored as a bitfield because the number of touch ids varies, 668 // but we currently don't need more than 32 touches at a time. 669 const unsigned int touch_ids_bitfield_; 670 }; 671 672 } // namespace ui 673 674 #endif // UI_EVENTS_EVENT_H_ 675