converter.dart 8.76 KB
Newer Older
Ian Hickson's avatar
Ian Hickson 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' as ui show PointerData, PointerChange, PointerSignalKind;
Ian Hickson's avatar
Ian Hickson committed
6 7 8

import 'events.dart';

9 10 11 12 13 14 15
// 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) {
16 17
    case PointerDeviceKind.mouse:
      return buttons;
18 19 20 21 22
    case PointerDeviceKind.touch:
    case PointerDeviceKind.stylus:
    case PointerDeviceKind.invertedStylus:
      return buttons | kPrimaryButton;
    default:
23 24 25
      // 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;
26 27 28
  }
}

29
/// Converts from engine pointer data to framework pointer events.
30 31 32 33
///
/// 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
34
class PointerEventConverter {
35 36
  PointerEventConverter._();

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

  static double _toLogicalPixels(double physicalPixels, double devicePixelRatio) =>
      physicalPixels == null ? null : physicalPixels / devicePixelRatio;
Ian Hickson's avatar
Ian Hickson committed
230
}