events.dart 15.9 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.

Ian Hickson's avatar
Ian Hickson committed
5
import 'dart:ui' show Point, Offset;
6

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

Ian Hickson's avatar
Ian Hickson committed
9
export 'dart:ui' show Point, Offset;
10

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/// The kind of pointer device.
enum PointerDeviceKind {
  /// A touch-based pointer device.
  touch,

  /// A pointer device with a stylus.
  stylus,

  /// A pointer device with a stylus that has been inverted.
  invertedStylus,

  /// A mouse-based pointer device.
  mouse
}

26 27 28 29
/// 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.
30
const int kPrimaryMouseButton = 0x01;
31 32 33 34 35

/// 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.
36
const int kSecondaryMouseButton = 0x02;
37 38 39 40 41

/// 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.
42
const int kPrimaryStylusButton = 0x02;
43 44 45 46 47 48

/// 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.
49
const int kMiddleMouseButton = 0x04;
50 51 52 53 54

/// 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.
55
const int kSecondaryStylusButton = 0x04;
56 57 58 59 60

/// 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.
61
const int kBackMouseButton = 0x08;
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

/// 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;
85

Ian Hickson's avatar
Ian Hickson committed
86 87
/// Base class for touch, stylus, or mouse events.
abstract class PointerEvent {
88 89
  /// 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
90 91
  const PointerEvent({
    this.timeStamp: Duration.ZERO,
92
    this.pointer: 0,
Ian Hickson's avatar
Ian Hickson committed
93 94 95
    this.kind: PointerDeviceKind.touch,
    this.position: Point.origin,
    this.delta: Offset.zero,
96 97 98
    this.buttons: 0,
    this.down: false,
    this.obscured: false,
Ian Hickson's avatar
Ian Hickson committed
99 100 101
    this.pressure: 1.0,
    this.pressureMin: 1.0,
    this.pressureMax: 1.0,
102 103 104 105 106 107 108 109
    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
110
  });
111

Ian Hickson's avatar
Ian Hickson committed
112 113 114 115
  /// 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
116
  final int pointer;
Ian Hickson's avatar
Ian Hickson committed
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

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

  /// 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
133
  final int buttons;
Ian Hickson's avatar
Ian Hickson committed
134

135 136 137
  /// 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
138
  final bool down;
Ian Hickson's avatar
Ian Hickson committed
139

140 141 142
  /// 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
143
  final bool obscured;
Ian Hickson's avatar
Ian Hickson committed
144 145 146 147 148

  /// 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
149
  final double pressure;
Ian Hickson's avatar
Ian Hickson committed
150 151 152 153

  /// 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
154
  final double pressureMin;
Ian Hickson's avatar
Ian Hickson committed
155 156 157 158

  /// 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
159
  final double pressureMax;
Ian Hickson's avatar
Ian Hickson committed
160 161 162 163 164

  /// 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
165
  final double distance;
Ian Hickson's avatar
Ian Hickson committed
166 167 168 169 170 171 172

  /// 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
173
  final double distanceMax;
Ian Hickson's avatar
Ian Hickson committed
174 175

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

  /// The radius of the contact ellipse along the minor axis, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
179
  final double radiusMinor;
Ian Hickson's avatar
Ian Hickson committed
180 181 182

  /// The minimum value that could be reported for radiusMajor and radiusMinor
  /// for this pointer, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
183
  final double radiusMin;
Ian Hickson's avatar
Ian Hickson committed
184 185 186

  /// The minimum value that could be reported for radiusMajor and radiusMinor
  /// for this pointer, in logical pixels.
Kris Giesing's avatar
Kris Giesing committed
187
  final double radiusMax;
Ian Hickson's avatar
Ian Hickson committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213

  /// 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
214 215
  final double orientation;

Ian Hickson's avatar
Ian Hickson committed
216 217 218 219 220 221 222 223 224 225 226
  /// 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;
227

228
  @override
Ian Hickson's avatar
Ian Hickson committed
229
  String toString() => '$runtimeType($position)';
230

231
  /// Returns a complete textual description of this event.
232
  String toStringFull() {
Ian Hickson's avatar
Ian Hickson committed
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
    return '$runtimeType('
             'timeStamp: $timeStamp, '
             'pointer: $pointer, '
             'kind: $kind, '
             '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'
           ')';
255
  }
256
}
Ian Hickson's avatar
Ian Hickson committed
257

258 259 260 261
/// 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
262
class PointerAddedEvent extends PointerEvent {
263 264 265
  /// Creates a pointer added event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
266 267 268 269 270 271
  const PointerAddedEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    Point position: Point.origin,
    bool obscured: false,
272 273
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    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,
    position: position,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

297 298 299 300
/// 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
301
class PointerRemovedEvent extends PointerEvent {
302 303 304
  /// Creates a pointer removed event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
305 306 307 308 309
  const PointerRemovedEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    bool obscured: false,
310 311
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
    double distanceMax: 0.0,
    double radiusMin: 0.0,
    double radiusMax: 0.0
  }) : super(
    timeStamp: timeStamp,
    pointer: pointer,
    kind: kind,
    position: null,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax
  );
}

329
/// The pointer has made contact with the device.
Ian Hickson's avatar
Ian Hickson committed
330
class PointerDownEvent extends PointerEvent {
331 332 333
  /// Creates a pointer down event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
334 335 336 337 338 339 340
  const PointerDownEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    Point position: Point.origin,
    int buttons: 0,
    bool obscured: false,
341 342 343
    double pressure: 1.0,
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
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 370 371 372
    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,
    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
  );
}

373
/// The pointer has moved with respect to the device.
Ian Hickson's avatar
Ian Hickson committed
374
class PointerMoveEvent extends PointerEvent {
375 376 377
  /// Creates a pointer move event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
378 379 380 381 382 383 384 385 386
  const PointerMoveEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    Point position: Point.origin,
    Offset delta: Offset.zero,
    int buttons: 0,
    bool down: false,
    bool obscured: false,
387 388 389
    double pressure: 1.0,
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
    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,
    pointer: pointer,
    kind: kind,
    position: position,
    delta: delta,
    buttons: buttons,
    down: down,
    obscured: obscured,
    pressure: pressure,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMajor: radiusMajor,
    radiusMinor: radiusMinor,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

421
/// The pointer has stopped making contact with the device.
Ian Hickson's avatar
Ian Hickson committed
422
class PointerUpEvent extends PointerEvent {
423 424 425
  /// Creates a pointer up event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
426 427 428 429 430 431 432
  const PointerUpEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    Point position: Point.origin,
    int buttons: 0,
    bool obscured: false,
433 434
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
    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,
    position: position,
    buttons: buttons,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}

459
/// The input from the pointer is no longer directed towards this receiver.
Ian Hickson's avatar
Ian Hickson committed
460
class PointerCancelEvent extends PointerEvent {
461 462 463
  /// Creates a pointer cancel event.
  ///
  /// All of the argument must be non-null.
Ian Hickson's avatar
Ian Hickson committed
464 465 466 467 468 469 470
  const PointerCancelEvent({
    Duration timeStamp: Duration.ZERO,
    int pointer: 0,
    PointerDeviceKind kind: PointerDeviceKind.touch,
    Point position: Point.origin,
    int buttons: 0,
    bool obscured: false,
471 472
    double pressureMin: 1.0,
    double pressureMax: 1.0,
Ian Hickson's avatar
Ian Hickson committed
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
    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,
    position: position,
    buttons: buttons,
    obscured: obscured,
    pressureMin: pressureMin,
    pressureMax: pressureMax,
    distance: distance,
    distanceMax: distanceMax,
    radiusMin: radiusMin,
    radiusMax: radiusMax,
    orientation: orientation,
    tilt: tilt
  );
}