converter.dart 9.25 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
Ian Hickson's avatar
Ian Hickson committed
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5

6
import 'dart:ui' as ui show PointerData, PointerChange, PointerSignalKind;
Ian Hickson's avatar
Ian Hickson committed
7 8 9

import 'events.dart';

10 11 12 13 14 15 16
// Add `kPrimaryButton` to [buttons] when a pointer of certain devices is down.
//
// TODO(tongmu): This patch is supposed to be done by embedders. Patching it
// in framework is a workaround before [PointerEventConverter] is moved to embedders.
// https://github.com/flutter/flutter/issues/30454
int _synthesiseDownButtons(int buttons, PointerDeviceKind kind) {
  switch (kind) {
17 18
    case PointerDeviceKind.mouse:
      return buttons;
19 20 21 22 23
    case PointerDeviceKind.touch:
    case PointerDeviceKind.stylus:
    case PointerDeviceKind.invertedStylus:
      return buttons | kPrimaryButton;
    default:
24 25 26
      // We have no information about the device but we know we never want
      // buttons to be 0 when the pointer is down.
      return buttons == 0 ? kPrimaryButton : buttons;
27 28 29
  }
}

30
/// Converts from engine pointer data to framework pointer events.
31 32 33 34
///
/// This takes [PointerDataPacket] objects, as received from the engine via
/// [dart:ui.Window.onPointerDataPacket], and converts them to [PointerEvent]
/// objects.
Ian Hickson's avatar
Ian Hickson committed
35
class PointerEventConverter {
36
  // This class is not meant to be instantiated or extended; this constructor
37 38
  // prevents instantiation and extension.
  // ignore: unused_element
39 40
  PointerEventConverter._();

41 42
  /// Expand the given packet of pointer data into a sequence of framework
  /// pointer events.
43 44 45 46 47
  ///
  /// The `devicePixelRatio` argument (usually given the value from
  /// [dart:ui.Window.devicePixelRatio]) is used to convert the incoming data
  /// from physical coordinates to logical pixels. See the discussion at
  /// [PointerEvent] for more details on the [PointerEvent] coordinate space.
48
  static Iterable<PointerEvent> expand(Iterable<ui.PointerData> data, double devicePixelRatio) sync* {
49
    for (final ui.PointerData datum in data) {
50
      final Offset position = Offset(datum.physicalX, datum.physicalY) / devicePixelRatio;
51
      assert(position != null);
52
      final Offset delta = Offset(datum.physicalDeltaX, datum.physicalDeltaY) / devicePixelRatio;
53 54 55 56
      final double radiusMinor = _toLogicalPixels(datum.radiusMinor, devicePixelRatio);
      final double radiusMajor = _toLogicalPixels(datum.radiusMajor, devicePixelRatio);
      final double radiusMin = _toLogicalPixels(datum.radiusMin, devicePixelRatio);
      final double radiusMax = _toLogicalPixels(datum.radiusMax, devicePixelRatio);
57 58
      final Duration timeStamp = datum.timeStamp;
      final PointerDeviceKind kind = datum.kind;
59
      assert(datum.change != null);
60 61 62
      if (datum.signalKind == null || datum.signalKind == ui.PointerSignalKind.none) {
        switch (datum.change) {
          case ui.PointerChange.add:
63
            yield PointerAddedEvent(
64 65 66 67 68 69 70 71 72
              timeStamp: timeStamp,
              kind: kind,
              device: datum.device,
              position: position,
              obscured: datum.obscured,
              pressureMin: datum.pressureMin,
              pressureMax: datum.pressureMax,
              distance: datum.distance,
              distanceMax: datum.distanceMax,
73 74
              radiusMin: radiusMin,
              radiusMax: radiusMax,
75
              orientation: datum.orientation,
76
              tilt: datum.tilt,
77
              embedderId: datum.embedderId,
78
            );
79 80
            break;
          case ui.PointerChange.hover:
81
            yield PointerHoverEvent(
82 83 84 85
              timeStamp: timeStamp,
              kind: kind,
              device: datum.device,
              position: position,
86
              delta: delta,
87 88 89 90 91 92
              buttons: datum.buttons,
              obscured: datum.obscured,
              pressureMin: datum.pressureMin,
              pressureMax: datum.pressureMax,
              distance: datum.distance,
              distanceMax: datum.distanceMax,
93
              size: datum.size,
94 95 96 97
              radiusMajor: radiusMajor,
              radiusMinor: radiusMinor,
              radiusMin: radiusMin,
              radiusMax: radiusMax,
98
              orientation: datum.orientation,
99
              tilt: datum.tilt,
100
              synthesized: datum.synthesized,
101
              embedderId: datum.embedderId,
102
            );
103 104 105
            break;
          case ui.PointerChange.down:
            yield PointerDownEvent(
106
              timeStamp: timeStamp,
107
              pointer: datum.pointerIdentifier,
108
              kind: kind,
109
              device: datum.device,
110
              position: position,
111
              buttons: _synthesiseDownButtons(datum.buttons, kind),
112 113 114 115 116
              obscured: datum.obscured,
              pressure: datum.pressure,
              pressureMin: datum.pressureMin,
              pressureMax: datum.pressureMax,
              distanceMax: datum.distanceMax,
117
              size: datum.size,
118 119 120 121
              radiusMajor: radiusMajor,
              radiusMinor: radiusMinor,
              radiusMin: radiusMin,
              radiusMax: radiusMax,
122
              orientation: datum.orientation,
123
              tilt: datum.tilt,
124
              embedderId: datum.embedderId,
125
            );
126 127 128
            break;
          case ui.PointerChange.move:
            yield PointerMoveEvent(
Ian Hickson's avatar
Ian Hickson committed
129
              timeStamp: timeStamp,
130
              pointer: datum.pointerIdentifier,
Ian Hickson's avatar
Ian Hickson committed
131
              kind: kind,
132
              device: datum.device,
Ian Hickson's avatar
Ian Hickson committed
133
              position: position,
134
              delta: delta,
135
              buttons: _synthesiseDownButtons(datum.buttons, kind),
Ian Hickson's avatar
Ian Hickson committed
136
              obscured: datum.obscured,
137 138
              pressure: datum.pressure,
              pressureMin: datum.pressureMin,
Ian Hickson's avatar
Ian Hickson committed
139 140
              pressureMax: datum.pressureMax,
              distanceMax: datum.distanceMax,
141
              size: datum.size,
142 143 144 145
              radiusMajor: radiusMajor,
              radiusMinor: radiusMinor,
              radiusMin: radiusMin,
              radiusMax: radiusMax,
Ian Hickson's avatar
Ian Hickson committed
146
              orientation: datum.orientation,
147
              tilt: datum.tilt,
148
              platformData: datum.platformData,
149
              synthesized: datum.synthesized,
150
              embedderId: datum.embedderId,
Ian Hickson's avatar
Ian Hickson committed
151
            );
152 153
            break;
          case ui.PointerChange.up:
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
            yield PointerUpEvent(
              timeStamp: timeStamp,
              pointer: datum.pointerIdentifier,
              kind: kind,
              device: datum.device,
              position: position,
              buttons: datum.buttons,
              obscured: datum.obscured,
              pressure: datum.pressure,
              pressureMin: datum.pressureMin,
              pressureMax: datum.pressureMax,
              distance: datum.distance,
              distanceMax: datum.distanceMax,
              size: datum.size,
              radiusMajor: radiusMajor,
              radiusMinor: radiusMinor,
              radiusMin: radiusMin,
              radiusMax: radiusMax,
              orientation: datum.orientation,
              tilt: datum.tilt,
174
              embedderId: datum.embedderId,
175 176
            );
            break;
177
          case ui.PointerChange.cancel:
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
            yield PointerCancelEvent(
              timeStamp: timeStamp,
              pointer: datum.pointerIdentifier,
              kind: kind,
              device: datum.device,
              position: position,
              buttons: datum.buttons,
              obscured: datum.obscured,
              pressureMin: datum.pressureMin,
              pressureMax: datum.pressureMax,
              distance: datum.distance,
              distanceMax: datum.distanceMax,
              size: datum.size,
              radiusMajor: radiusMajor,
              radiusMinor: radiusMinor,
              radiusMin: radiusMin,
              radiusMax: radiusMax,
              orientation: datum.orientation,
              tilt: datum.tilt,
197
              embedderId: datum.embedderId,
198
            );
199 200 201
            break;
          case ui.PointerChange.remove:
            yield PointerRemovedEvent(
Ian Hickson's avatar
Ian Hickson committed
202 203
              timeStamp: timeStamp,
              kind: kind,
204
              device: datum.device,
205
              position: position,
Ian Hickson's avatar
Ian Hickson committed
206 207 208 209
              obscured: datum.obscured,
              pressureMin: datum.pressureMin,
              pressureMax: datum.pressureMax,
              distanceMax: datum.distanceMax,
210 211
              radiusMin: radiusMin,
              radiusMax: radiusMax,
212
              embedderId: datum.embedderId,
Ian Hickson's avatar
Ian Hickson committed
213
            );
214 215 216
            break;
        }
      } else {
217
        switch (datum.signalKind!) {
218 219 220 221
          case ui.PointerSignalKind.scroll:
            final Offset scrollDelta =
                Offset(datum.scrollDeltaX, datum.scrollDeltaY) / devicePixelRatio;
            yield PointerScrollEvent(
222 223 224 225
              timeStamp: timeStamp,
              kind: kind,
              device: datum.device,
              position: position,
226
              scrollDelta: scrollDelta,
227
              embedderId: datum.embedderId,
228
            );
229 230 231 232 233 234 235 236
            break;
          case ui.PointerSignalKind.none:
            assert(false); // This branch should already have 'none' filtered out.
            break;
          case ui.PointerSignalKind.unknown:
            // Ignore unknown signals.
            break;
        }
Ian Hickson's avatar
Ian Hickson committed
237 238 239
      }
    }
  }
240

241
  static double _toLogicalPixels(double physicalPixels, double devicePixelRatio) => physicalPixels / devicePixelRatio;
Ian Hickson's avatar
Ian Hickson committed
242
}