events.dart 17.4 KB
Newer Older
Kris Giesing's avatar
Kris Giesing committed
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:ui' show Point, Offset, PointerDeviceKind;
6

7 8
import 'package:flutter/foundation.dart';

9
export 'dart:ui' show Point, Offset, PointerDeviceKind;
10

11 12 13 14
/// The bit of [PointerEvent.buttons] that corresponds to the primary mouse button.
///
/// The primary mouse button is typically the left button on the top of the
/// mouse but can be reconfigured to be a different physical button.
15
const int kPrimaryMouseButton = 0x01;
16 17 18 19 20

/// The bit of [PointerEvent.buttons] that corresponds to the secondary mouse button.
///
/// The secondary mouse button is typically the right button on the top of the
/// mouse but can be reconfigured to be a different physical button.
21
const int kSecondaryMouseButton = 0x02;
22 23 24 25 26

/// The bit of [PointerEvent.buttons] that corresponds to the primary stylus button.
///
/// The primary stylus button is typically the top of the stylus and near the
/// tip but can be reconfigured to be a different physical button.
27
const int kPrimaryStylusButton = 0x02;
28 29 30 31 32 33

/// The bit of [PointerEvent.buttons] that corresponds to the middle mouse button.
///
/// The middle mouse button is typically between the left and right buttons on
/// the top of the mouse but can be reconfigured to be a different physical
/// button.
34
const int kMiddleMouseButton = 0x04;
35 36 37 38 39

/// The bit of [PointerEvent.buttons] that corresponds to the secondary stylus button.
///
/// The secondary stylus button is typically on the end of the stylus fartherest
/// from the tip but can be reconfigured to be a different physical button.
40
const int kSecondaryStylusButton = 0x04;
41 42 43 44 45

/// The bit of [PointerEvent.buttons] that corresponds to the back mouse button.
///
/// The back mouse button is typically on the left side of the mouse but can be
/// reconfigured to be a different physical button.
46
const int kBackMouseButton = 0x08;
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

/// The bit of [PointerEvent.buttons] that corresponds to the forward mouse button.
///
/// The forward mouse button is typically on the right side of the mouse but can
/// be reconfigured to be a different physical button.
const int kForwardMouseButton = 0x10;

/// The bit of [PointerEvent.buttons] that corresponds to the nth mouse button.
///
/// The number argument can be at most 62.
///
/// See [kPrimaryMouseButton], [kSecondaryMouseButton], [kMiddleMouseButton],
/// [kBackMouseButton], and [kForwardMouseButton] for semantic names for some
/// mouse buttons.
int nthMouseButton(int number) => (kPrimaryMouseButton << (number - 1)) & kMaxUnsignedSMI;

/// The bit of [PointerEvent.buttons] that corresponds to the nth stylus button.
///
/// The number argument can be at most 62.
///
/// See [kPrimaryStylusButton] and [kSecondaryStylusButton] for semantic names
/// for some stylus buttons.
int nthStylusButton(int number) => (kPrimaryStylusButton << (number - 1)) & kMaxUnsignedSMI;
70

Ian Hickson's avatar
Ian Hickson committed
71 72
/// Base class for touch, stylus, or mouse events.
abstract class PointerEvent {
73 74
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
Ian Hickson's avatar
Ian Hickson committed
75 76
  const PointerEvent({
    this.timeStamp: Duration.ZERO,
77
    this.pointer: 0,
Ian Hickson's avatar
Ian Hickson committed
78
    this.kind: PointerDeviceKind.touch,
79
    this.device: 0,
Ian Hickson's avatar
Ian Hickson committed
80 81
    this.position: Point.origin,
    this.delta: Offset.zero,
82 83 84
    this.buttons: 0,
    this.down: false,
    this.obscured: false,
Ian Hickson's avatar
Ian Hickson committed
85 86 87
    this.pressure: 1.0,
    this.pressureMin: 1.0,
    this.pressureMax: 1.0,
88 89 90 91 92 93 94 95
    this.distance: 0.0,
    this.distanceMax: 0.0,
    this.radiusMajor: 0.0,
    this.radiusMinor: 0.0,
    this.radiusMin: 0.0,
    this.radiusMax: 0.0,
    this.orientation: 0.0,
    this.tilt: 0.0
Ian Hickson's avatar
Ian Hickson committed
96
  });
97

Ian Hickson's avatar
Ian Hickson committed
98 99 100 101
  /// Time of event dispatch, relative to an arbitrary timeline.
  final Duration timeStamp;

  /// Unique identifier for the pointer, not reused.
Kris Giesing's avatar
Kris Giesing committed
102
  final int pointer;
Ian Hickson's avatar
Ian Hickson committed
103 104 105 106

  /// The kind of input device for which the event was generated.
  final PointerDeviceKind kind;

107 108 109
  /// Unique identifier for the pointing device, reused across interactions.
  final int device;

Ian Hickson's avatar
Ian Hickson committed
110 111 112 113 114 115 116 117 118 119 120 121
  /// Coordinate of the position of the pointer, in logical pixels in the global
  /// coordinate space.
  final Point position;

  /// Distance in logical pixels that the pointer moved since the last
  /// PointerMoveEvent. Always 0.0 for down, up, and cancel events.
  final Offset delta;

  /// Bit field using the *Button constants (primaryMouseButton,
  /// secondaryStylusButton, etc). For example, if this has the value 6 and the
  /// [kind] is [PointerDeviceKind.invertedStylus], then this indicates an
  /// upside-down stylus with both its primary and secondary buttons pressed.
Kris Giesing's avatar
Kris Giesing committed
122
  final int buttons;
Ian Hickson's avatar
Ian Hickson committed
123

124 125 126
  /// Set if the pointer is currently down. For touch and stylus pointers, this
  /// means the object (finger, pen) is in contact with the input surface. For
  /// mice, it means a button is pressed.
Kris Giesing's avatar
Kris Giesing committed
127
  final bool down;
Ian Hickson's avatar
Ian Hickson committed
128

129 130 131
  /// Set if an application from a different security domain is in any way
  /// obscuring this application's window. (Aspirational; not currently
  /// implemented.)
Kris Giesing's avatar
Kris Giesing committed
132
  final bool obscured;
Ian Hickson's avatar
Ian Hickson committed
133 134 135 136 137

  /// The pressure of the touch as a number ranging from 0.0, indicating a touch
  /// with no discernible pressure, to 1.0, indicating a touch with "normal"
  /// pressure, and possibly beyond, indicating a stronger touch. For devices
  /// that do not detect pressure (e.g. mice), returns 1.0.
Kris Giesing's avatar
Kris Giesing committed
138
  final double pressure;
Ian Hickson's avatar
Ian Hickson committed
139 140 141 142

  /// The minimum value that [pressure] can return for this pointer. For devices
  /// that do not detect pressure (e.g. mice), returns 1.0. This will always be
  /// a number less than or equal to 1.0.
Kris Giesing's avatar
Kris Giesing committed
143
  final double pressureMin;
Ian Hickson's avatar
Ian Hickson committed
144 145 146 147

  /// The maximum value that [pressure] can return for this pointer. For devices
  /// that do not detect pressure (e.g. mice), returns 1.0. This will always be
  /// a greater than or equal to 1.0.
Kris Giesing's avatar
Kris Giesing committed
148
  final double pressureMax;
Ian Hickson's avatar
Ian Hickson committed
149 150 151 152 153

  /// The distance of the detected object from the input surface (e.g. the
  /// distance of a stylus or finger from a touch screen), in arbitrary units on
  /// an arbitrary (not necessarily linear) scale. If the pointer is down, this
  /// is 0.0 by definition.
Kris Giesing's avatar
Kris Giesing committed
154
  final double distance;
Ian Hickson's avatar
Ian Hickson committed
155 156 157 158 159 160 161

  /// The minimum value that a distance can return for this pointer (always 0.0).
  final double distanceMin = 0.0;

  /// The maximum value that a distance can return for this pointer. If this
  /// input device cannot detect "hover touch" input events, then this will be
  /// 0.0.
Kris Giesing's avatar
Kris Giesing committed
162
  final double distanceMax;
Ian Hickson's avatar
Ian Hickson committed
163 164

  /// The radius of the contact ellipse along the major axis, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
165
  final double radiusMajor;
Ian Hickson's avatar
Ian Hickson committed
166 167

  /// The radius of the contact ellipse along the minor axis, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
168
  final double radiusMinor;
Ian Hickson's avatar
Ian Hickson committed
169 170 171

  /// The minimum value that could be reported for radiusMajor and radiusMinor
  /// for this pointer, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
172
  final double radiusMin;
Ian Hickson's avatar
Ian Hickson committed
173 174 175

  /// The minimum value that could be reported for radiusMajor and radiusMinor
  /// for this pointer, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
176
  final double radiusMax;
Ian Hickson's avatar
Ian Hickson committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

  /// For PointerDeviceKind.touch events:
  ///
  /// The angle of the contact ellipse, in radius in the range:
  ///
  ///    -pi/2 < orientation <= pi/2
  ///
  /// ...giving the angle of the major axis of the ellipse with the y-axis
  /// (negative angles indicating an orientation along the top-left /
  /// bottom-right diagonal, positive angles indicating an orientation along the
  /// top-right / bottom-left diagonal, and zero indicating an orientation
  /// parallel with the y-axis).
  ///
  /// For PointerDeviceKind.stylus and PointerDeviceKind.invertedStylus events:
  ///
  /// The angle of the stylus, in radians in the range:
  ///
  ///    -pi < orientation <= pi
  ///
  /// ...giving the angle of the axis of the stylus projected onto the input
  /// surface, relative to the positive y-axis of that surface (thus 0.0
  /// indicates the stylus, if projected onto that surface, would go from the
  /// contact point vertically up in the positive y-axis direction, pi would
  /// indicate that the stylus would go down in the negative y-axis direction;
  /// pi/4 would indicate that the stylus goes up and to the right, -pi/2 would
  /// indicate that the stylus goes to the left, etc).
Kris Giesing's avatar
Kris Giesing committed
203 204
  final double orientation;

Ian Hickson's avatar
Ian Hickson committed
205 206 207 208 209 210 211 212 213 214 215
  /// For PointerDeviceKind.stylus and PointerDeviceKind.invertedStylus events:
  ///
  /// The angle of the stylus, in radians in the range:
  ///
  ///    0 <= tilt <= pi/2
  ///
  /// ...giving the angle of the axis of the stylus, relative to the axis
  /// perpendicular to the input surface (thus 0.0 indicates the stylus is
  /// orthogonal to the plane of the input surface, while pi/2 indicates that
  /// the stylus is flat on that surface).
  final double tilt;
216

217
  @override
Ian Hickson's avatar
Ian Hickson committed
218
  String toString() => '$runtimeType($position)';
219

220
  /// Returns a complete textual description of this event.
221
  String toStringFull() {
Ian Hickson's avatar
Ian Hickson committed
222 223 224 225
    return '$runtimeType('
             'timeStamp: $timeStamp, '
             'pointer: $pointer, '
             'kind: $kind, '
226
             'device: $device, '
Ian Hickson's avatar
Ian Hickson committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
             'position: $position, '
             'delta: $delta, '
             'buttons: $buttons, '
             'down: $down, '
             'obscured: $obscured, '
             'pressure: $pressure, '
             'pressureMin: $pressureMin, '
             'pressureMax: $pressureMax, '
             'distance: $distance, '
             'distanceMin: $distanceMin, '
             'distanceMax: $distanceMax, '
             'radiusMajor: $radiusMajor, '
             'radiusMinor: $radiusMinor, '
             'radiusMin: $radiusMin, '
             'radiusMax: $radiusMax, '
             'orientation: $orientation, '
             'tilt: $tilt'
           ')';
245
  }
246
}
Ian Hickson's avatar
Ian Hickson committed
247

248 249 250 251
/// The device has started tracking the pointer.
///
/// For example, the pointer might be hovering above the device, having not yet
/// made contact with the surface of the device.
Ian Hickson's avatar
Ian Hickson committed
252
class PointerAddedEvent extends PointerEvent {
253 254 255
  /// Creates a pointer added event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
256 257 258
  const PointerAddedEvent({
    Duration timeStamp: Duration.ZERO,
    PointerDeviceKind kind: PointerDeviceKind.touch,
259
    int device: 0,
Ian Hickson's avatar
Ian Hickson committed
260 261
    Point position: Point.origin,
    bool obscured: false,
262 263
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
264 265 266 267 268 269 270 271 272
    double distance: 0.0,
    double distanceMax: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0,
    double orientation: 0.0,
    double tilt: 0.0
  }) : super(
    timeStamp: timeStamp,
    kind: kind,
273
    device: device,
Ian Hickson's avatar
Ian Hickson committed
274 275 276 277 278 279 280 281 282 283 284 285 286
    position: position,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

287 288 289 290
/// The device is no longer tracking the pointer.
///
/// For example, the pointer might have drifted out of the device's hover
/// detection range or might have been disconnected from the system entirely.
Ian Hickson's avatar
Ian Hickson committed
291
class PointerRemovedEvent extends PointerEvent {
292 293 294
  /// Creates a pointer removed event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
295 296 297
  const PointerRemovedEvent({
    Duration timeStamp: Duration.ZERO,
    PointerDeviceKind kind: PointerDeviceKind.touch,
298
    int device: 0,
Ian Hickson's avatar
Ian Hickson committed
299
    bool obscured: false,
300 301
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
302 303 304 305 306 307
    double distanceMax: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0
  }) : super(
    timeStamp: timeStamp,
    kind: kind,
308
    device: device,
Ian Hickson's avatar
Ian Hickson committed
309 310 311 312 313 314 315 316 317 318
    position: null,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax
  );
}

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
/// The pointer has moved with respect to the device while the pointer is not
/// in contact with the device.
///
/// See also:
///
///  * [PointerMoveEvent], which reports movement while the pointer is in
///    contact with the device.
class PointerHoverEvent extends PointerEvent {
  /// Creates a pointer hover event.
  ///
  /// All of the argument must be non-null.
  const PointerHoverEvent({
    Duration timeStamp: Duration.ZERO,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    int device: 0,
    Point position: Point.origin,
    Offset delta: Offset.zero,
    int buttons: 0,
    bool obscured: false,
    double pressureMin: 1.0,
    double pressureMax: 1.0,
    double distance: 0.0,
    double distanceMax: 0.0,
    double radiusMajor: 0.0,
    double radiusMinor: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0,
    double orientation: 0.0,
    double tilt: 0.0
  }) : super(
    timeStamp: timeStamp,
    kind: kind,
    device: device,
    position: position,
    delta: delta,
    buttons: buttons,
    down: false,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMajor: radiusMajor,
    radiusMinor: radiusMinor,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

370
/// The pointer has made contact with the device.
Ian Hickson's avatar
Ian Hickson committed
371
class PointerDownEvent extends PointerEvent {
372 373 374
  /// Creates a pointer down event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
375 376 377 378
  const PointerDownEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
379
    int device: 0,
Ian Hickson's avatar
Ian Hickson committed
380 381 382
    Point position: Point.origin,
    int buttons: 0,
    bool obscured: false,
383 384 385
    double pressure: 1.0,
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
386 387 388 389 390 391 392 393 394 395 396
    double distanceMax: 0.0,
    double radiusMajor: 0.0,
    double radiusMinor: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0,
    double orientation: 0.0,
    double tilt: 0.0
  }) : super(
    timeStamp: timeStamp,
    pointer: pointer,
    kind: kind,
397
    device: device,
Ian Hickson's avatar
Ian Hickson committed
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
    position: position,
    buttons: buttons,
    down: true,
    obscured: obscured,
    pressure: pressure,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: 0.0,
    distanceMax: distanceMax,
    radiusMajor: radiusMajor,
    radiusMinor: radiusMinor,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

416 417 418 419 420 421 422
/// The pointer has moved with respect to the device while the pointer is in
/// contact with the device.
///
/// See also:
///
///  * [PointerHoverEvent], which reports movement while the pointer is not in
///    contact with the device.
Ian Hickson's avatar
Ian Hickson committed
423
class PointerMoveEvent extends PointerEvent {
424 425 426
  /// Creates a pointer move event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
427 428 429 430
  const PointerMoveEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
431
    int device: 0,
Ian Hickson's avatar
Ian Hickson committed
432 433 434 435
    Point position: Point.origin,
    Offset delta: Offset.zero,
    int buttons: 0,
    bool obscured: false,
436 437 438
    double pressure: 1.0,
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
439 440 441 442 443 444 445 446 447 448 449
    double distanceMax: 0.0,
    double radiusMajor: 0.0,
    double radiusMinor: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0,
    double orientation: 0.0,
    double tilt: 0.0
  }) : super(
    timeStamp: timeStamp,
    pointer: pointer,
    kind: kind,
450
    device: device,
Ian Hickson's avatar
Ian Hickson committed
451 452 453
    position: position,
    delta: delta,
    buttons: buttons,
454
    down: true,
Ian Hickson's avatar
Ian Hickson committed
455 456 457 458
    obscured: obscured,
    pressure: pressure,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
459
    distance: 0.0,
Ian Hickson's avatar
Ian Hickson committed
460 461 462 463 464 465 466 467 468 469
    distanceMax: distanceMax,
    radiusMajor: radiusMajor,
    radiusMinor: radiusMinor,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

470
/// The pointer has stopped making contact with the device.
Ian Hickson's avatar
Ian Hickson committed
471
class PointerUpEvent extends PointerEvent {
472 473 474
  /// Creates a pointer up event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
475 476 477 478
  const PointerUpEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
479
    int device: 0,
Ian Hickson's avatar
Ian Hickson committed
480 481 482
    Point position: Point.origin,
    int buttons: 0,
    bool obscured: false,
483 484
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
485 486 487 488 489 490 491 492 493 494
    double distance: 0.0,
    double distanceMax: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0,
    double orientation: 0.0,
    double tilt: 0.0
  }) : super(
    timeStamp: timeStamp,
    pointer: pointer,
    kind: kind,
495
    device: device,
Ian Hickson's avatar
Ian Hickson committed
496 497
    position: position,
    buttons: buttons,
498
    down: false,
Ian Hickson's avatar
Ian Hickson committed
499 500 501 502 503 504 505 506 507 508 509 510
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

511
/// The input from the pointer is no longer directed towards this receiver.
Ian Hickson's avatar
Ian Hickson committed
512
class PointerCancelEvent extends PointerEvent {
513 514 515
  /// Creates a pointer cancel event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
516 517 518 519
  const PointerCancelEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
520
    int device: 0,
Ian Hickson's avatar
Ian Hickson committed
521 522 523
    Point position: Point.origin,
    int buttons: 0,
    bool obscured: false,
524 525
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
526 527 528 529 530 531 532 533 534 535
    double distance: 0.0,
    double distanceMax: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0,
    double orientation: 0.0,
    double tilt: 0.0
  }) : super(
    timeStamp: timeStamp,
    pointer: pointer,
    kind: kind,
536
    device: device,
Ian Hickson's avatar
Ian Hickson committed
537 538
    position: position,
    buttons: buttons,
539
    down: false,
Ian Hickson's avatar
Ian Hickson committed
540 541 542 543 544 545 546 547 548 549 550
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}