@stim-cli/server 1.21.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,6 +65,29 @@ enum TouchPhase {
65
65
  }
66
66
  }
67
67
 
68
+ struct SimulatorTouchSequence {
69
+ private var originEdge: UInt32 = 0
70
+
71
+ mutating func edge(for phase: TouchPhase, at point: CGPoint, isMultiTouch: Bool = false) -> UInt32 {
72
+ if phase == .down {
73
+ originEdge = isMultiTouch ? 0 : Self.edge(at: point)
74
+ }
75
+ let edge = originEdge
76
+ if phase == .up { originEdge = 0 }
77
+ return edge
78
+ }
79
+
80
+ // Indigo's native screen-edge identifiers follow Siniulator's ScreenGeometry.edge:
81
+ // https://github.com/kmagiera/Siniulator/blob/e181521a32595c2e537e1ee6c359aae254dbfed3/Sources/Siniulator/ScreenView.swift#L32-L38
82
+ private static func edge(at point: CGPoint) -> UInt32 {
83
+ if point.y >= 0.97 { return 3 }
84
+ if point.y <= 0.03 { return 1 }
85
+ if point.x <= 0.03 { return 2 }
86
+ if point.x >= 0.97 { return 4 }
87
+ return 0
88
+ }
89
+ }
90
+
68
91
  /// Input for one booted simulator. It uses the simulator's CoreDevice HID
69
92
  /// service when the runtime has one, and SimulatorKit's legacy HID client
70
93
  /// otherwise. `isConnected` turns false once the CoreDevice connection closes,
@@ -74,6 +97,7 @@ enum TouchPhase {
74
97
  /// Construction performs synchronous CoreSimulator XPC lookups and must run off the main thread.
75
98
  final class SimulatorHID {
76
99
  private let transport: Transport
100
+ private var touchSequence = SimulatorTouchSequence()
77
101
  private let legacyUntil = Date().addingTimeInterval(10)
78
102
 
79
103
  private enum Transport {
@@ -104,9 +128,10 @@ final class SimulatorHID {
104
128
 
105
129
  /// `point` is a fraction of the screen in its native orientation, origin top-left.
106
130
  func touch(_ phase: TouchPhase, at point: CGPoint, second: CGPoint? = nil, screenID: UInt32 = 1) {
131
+ let edge = touchSequence.edge(for: phase, at: point, isMultiTouch: second != nil)
107
132
  switch transport {
108
- case .coreDevice(let coreDevice): coreDevice.touch(phase, at: point, second: second, screenID: screenID)
109
- case .legacy(let legacy): legacy.touch(phase, at: point, second: second, screenID: screenID)
133
+ case .coreDevice(let coreDevice): coreDevice.touch(phase, at: point, second: second, screenID: screenID, edge: edge)
134
+ case .legacy(let legacy): legacy.touch(phase, at: point, second: second, screenID: screenID, edge: edge)
110
135
  }
111
136
  }
112
137
 
@@ -211,12 +236,13 @@ final class CoreDeviceHID {
211
236
  }
212
237
 
213
238
  // dtuhidd's DigitizerTarget is 0 for the main screen and the screen ID for any other display.
214
- func touch(_ phase: TouchPhase, at point: CGPoint, second: CGPoint?, screenID: UInt32) {
239
+ func touch(_ phase: TouchPhase, at point: CGPoint, second: CGPoint?, screenID: UInt32, edge: UInt32) {
215
240
  let contact = xpc_dictionary_create(nil, nil, 0)
216
241
  xpc_dictionary_set_double(contact, "x", point.x)
217
242
  xpc_dictionary_set_double(contact, "y", point.y)
218
243
  let payload = dictionary([
219
- "eventType": phase == .down ? 0 : phase == .move ? 1 : 2, "edge": 0, "target": UInt64(screenID == 1 ? 0 : screenID),
244
+ "eventType": phase == .down ? 0 : phase == .move ? 1 : 2, "edge": UInt64(edge),
245
+ "target": UInt64(screenID == 1 ? 0 : screenID),
220
246
  ])
221
247
  xpc_dictionary_set_value(payload, "pointOne", contact)
222
248
  if let second {
@@ -313,17 +339,17 @@ private final class LegacyHID {
313
339
  // The simulator's SimulatorHID addresses a display's digitizer by its screen
314
340
  // ID with bit 30 set, and backboardd aborts on a target it has no service
315
341
  // for. The main display keeps its legacy target.
316
- func touch(_ phase: TouchPhase, at point: CGPoint, second: CGPoint?, screenID: UInt32) {
342
+ func touch(_ phase: TouchPhase, at point: CGPoint, second: CGPoint?, screenID: UInt32, edge: UInt32) {
317
343
  let target = screenID == 1 ? Self.mainScreenTarget : 0x4000_0000 | screenID
318
344
  var point = point
319
345
  // The builder returns nil for a drag that arrives within 16 ms of the previous message.
320
346
  let message: UnsafeMutableRawPointer?
321
347
  if var other = second {
322
348
  message = SimulatorKit.mouseMessage?(
323
- &point, &other, target, UInt(phase.eventType.rawValue), CGSize(width: 1, height: 1), 0)
349
+ &point, &other, target, UInt(phase.eventType.rawValue), CGSize(width: 1, height: 1), edge)
324
350
  } else {
325
351
  message = SimulatorKit.mouseMessage?(
326
- &point, nil, target, UInt(phase.eventType.rawValue), CGSize(width: 1, height: 1), 0)
352
+ &point, nil, target, UInt(phase.eventType.rawValue), CGSize(width: 1, height: 1), edge)
327
353
  }
328
354
  guard let message else { return }
329
355
  deliver(message)