@breakside/jskit 2023.18.3 → 2023.19.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.
Files changed (48) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/JS/JSLocale.js +14 -1
  7. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  8. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  9. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  10. package/Info.json +2 -2
  11. package/Node/io.breakside.jskit-bundle.js +2 -2
  12. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  13. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  14. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  15. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  16. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  17. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  18. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  19. package/Root/Frameworks/DOM/Info.yaml +1 -1
  20. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  21. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  22. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  23. package/Root/Frameworks/Foundation/JSLocale.js +14 -1
  24. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  25. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  26. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  27. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  28. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  29. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  30. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  31. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  32. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  33. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  34. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  35. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  36. package/Root/Frameworks/UIKit/UICollectionView.js +40 -20
  37. package/Root/Frameworks/UIKit/UIEvent.js +31 -0
  38. package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +11 -4
  39. package/Root/Frameworks/UIKit/UIListView.js +42 -22
  40. package/Root/Frameworks/UIKit/UIMenuView.js +32 -7
  41. package/Root/Frameworks/UIKit/UIPressGestureRecognizer.js +27 -34
  42. package/Root/Frameworks/UIKit/UIScrollGestureRecognizer.js +22 -5
  43. package/Root/Frameworks/UIKit/UIScrollView.js +22 -3
  44. package/Root/Frameworks/UIKit/UITapGestureRecognizer.js +23 -28
  45. package/Root/Frameworks/UIKit/UIWindow.js +47 -29
  46. package/Root/Frameworks/UIKit/UIWindowServer.js +10 -1
  47. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  48. package/package.json +1 -1
@@ -2385,53 +2385,73 @@ JSClass("UIListView", UIScrollView, {
2385
2385
 
2386
2386
  touchesBegan: function(touches, event){
2387
2387
  UIListView.$super.touchesBegan.call(this, touches, event);
2388
- if (touches.length > 1){
2389
- return;
2388
+ if (this._touch !== null){
2389
+ if (event.touchForIdentifier(this._touch.identifier) !== null){
2390
+ return;
2391
+ }
2390
2392
  }
2393
+ var touch = touches[0];
2391
2394
  this._touch = {
2392
- location0: touches[0].locationInWindow,
2395
+ identifier: touch.identifier,
2396
+ location0: touch.locationInWindow,
2393
2397
  cell: null,
2394
2398
  timer: JSTimer.scheduledTimerWithInterval(0.05, function(){
2395
2399
  this._touch.timer = null;
2396
- this._makeTouchActiveCell(touches[0], true);
2400
+ this._makeTouchActiveCell(touch, true);
2397
2401
  }, this)
2398
2402
  };
2399
2403
  },
2400
2404
 
2401
2405
  touchesMoved: function(touches, event){
2402
2406
  UIListView.$super.touchesMoved.call(this, touches, event);
2403
- if (this._touch !== null){
2404
- var location = touches[0].locationInWindow;
2405
- var diff = location.subtracting(this._touch.location0);
2406
- if ((diff.x * diff.x + diff.y * diff.y) > 2){
2407
- this._cancelTouchSelection();
2408
- }
2407
+ if (this._touch === null){
2408
+ return;
2409
+ }
2410
+ var touch = event.touchForIdentifier(this._touch.identifier);
2411
+ if (touches.indexOf(touch) < 0){
2412
+ return;
2413
+ }
2414
+ var location = touch.locationInWindow;
2415
+ var diff = location.subtracting(this._touch.location0);
2416
+ if ((diff.x * diff.x + diff.y * diff.y) > 2){
2417
+ this._cancelTouchSelection();
2409
2418
  }
2410
2419
  },
2411
2420
 
2412
2421
  touchesEnded: function(touches, event){
2413
2422
  UIListView.$super.touchesEnded.call(this, touches, event);
2414
- if (touches.length > 1){
2423
+ if (this._touch === null){
2415
2424
  return;
2416
2425
  }
2417
- if (this._touch !== null){
2418
- if (this._touch.timer !== null){
2419
- this._touch.timer.invalidate();
2420
- this._makeTouchActiveCell(touches[0]);
2426
+ var touch = event.touchForIdentifier(this._touch.identifier);
2427
+ if (touches.indexOf(touch) < 0){
2428
+ return;
2429
+ }
2430
+ if (this._touch.timer !== null){
2431
+ this._touch.timer.invalidate();
2432
+ if (touch !== null){
2433
+ this._makeTouchActiveCell(touch);
2421
2434
  }
2422
- if (this._touch.cell){
2423
- this._touch.cell.active = false;
2424
- this._setSelectedIndexPaths([this._touch.cell.indexPath], {notifyDelegate: true});
2425
- if (this.delegate && this.delegate.listViewDidFinishSelectingCellAtIndexPath){
2426
- this.delegate.listViewDidFinishSelectingCellAtIndexPath(this, this._touch.cell.indexPath);
2427
- }
2435
+ }
2436
+ if (this._touch.cell){
2437
+ this._touch.cell.active = false;
2438
+ this._setSelectedIndexPaths([this._touch.cell.indexPath], {notifyDelegate: true});
2439
+ if (this.delegate && this.delegate.listViewDidFinishSelectingCellAtIndexPath){
2440
+ this.delegate.listViewDidFinishSelectingCellAtIndexPath(this, this._touch.cell.indexPath);
2428
2441
  }
2429
- this._touch = null;
2430
2442
  }
2443
+ this._touch = null;
2431
2444
  },
2432
2445
 
2433
2446
  touchesCanceled: function(touches, event){
2434
2447
  UIListView.$super.touchesCanceled.call(this, touches, event);
2448
+ if (this._touch === null){
2449
+ return;
2450
+ }
2451
+ var touch = event.touchForIdentifier(this._touch.identifier);
2452
+ if (touches.indexOf(touch) < 0){
2453
+ return;
2454
+ }
2435
2455
  this._cancelTouchSelection();
2436
2456
  },
2437
2457
 
@@ -390,14 +390,22 @@ JSClass("UIMenuWindow", UIWindow, {
390
390
  // -----------------------------------------------------------------------
391
391
  // MARK: - Touch Events
392
392
 
393
+ _activeTouchInfo: null,
394
+
393
395
  touchesBegan: function(touches, event){
394
396
  if (this._isClosing){
395
397
  return;
396
398
  }
397
- if (touches.length > 1){
398
- return;
399
+ if (this._activeTouchInfo !== null){
400
+ if (event.touchForIdentifier(this._activeTouchInfo.identifier) !== null){
401
+ return;
402
+ }
399
403
  }
400
- var location = touches[0].locationInView(this);
404
+ var touch = touches[0];
405
+ this._activeTouchInfo = {
406
+ identifier: touch.identifier
407
+ };
408
+ var location = touch.locationInView(this);
401
409
  if (!this.containsPoint(location)){
402
410
  if (this._menu.supermenu && this._menu.supermenu.stylerProperties.window){
403
411
  this._menu.supermenu.stylerProperties.window.touchesBegan(touches, event);
@@ -411,10 +419,14 @@ JSClass("UIMenuWindow", UIWindow, {
411
419
  },
412
420
 
413
421
  touchesMoved: function(touches, event){
414
- if (this._isClosing){
422
+ if (this._activeTouchInfo === null){
415
423
  return;
416
424
  }
417
- var location = touches[0].locationInView(this);
425
+ var touch = event.touchForIdentifier(this._activeTouchInfo.identifier);
426
+ if (touches.indexOf(touch) < 0){
427
+ return;
428
+ }
429
+ var location = touch.locationInView(this);
418
430
  this._lastMoveLocation = location;
419
431
  this._adjustHighlightForLocation(this._lastMoveLocation);
420
432
  if (!this.containsPoint(location)){
@@ -428,10 +440,15 @@ JSClass("UIMenuWindow", UIWindow, {
428
440
  if (event.timestamp - this._itemDownTimestamp < 0.2){
429
441
  return;
430
442
  }
431
- if (this._isClosing){
443
+ if (this._activeTouchInfo === null){
432
444
  return;
433
445
  }
434
- var location = touches[0].locationInView(this);
446
+ var touch = event.touchForIdentifier(this._activeTouchInfo.identifier);
447
+ if (touches.indexOf(touch) < 0){
448
+ return;
449
+ }
450
+ this._activeTouchInfo = null;
451
+ var location = touch.locationInView(this);
435
452
  if (this.containsPoint(location)){
436
453
  this._performActionForHighlightedItem();
437
454
  }else{
@@ -444,6 +461,14 @@ JSClass("UIMenuWindow", UIWindow, {
444
461
  },
445
462
 
446
463
  touchesCanceled: function(touches, event){
464
+ if (this._activeTouchInfo === null){
465
+ return;
466
+ }
467
+ var touch = event.touchForIdentifier(this._activeTouchInfo.identifier);
468
+ if (touches.indexOf(touch) < 0){
469
+ return;
470
+ }
471
+ this._activeTouchInfo = null;
447
472
  },
448
473
 
449
474
  // -----------------------------------------------------------------------
@@ -36,48 +36,45 @@ JSClass("UIPressGestureRecognizer", UIGestureRecognizer, {
36
36
 
37
37
  // MARK: - Events
38
38
 
39
- began: false,
40
- beganLocation: null,
41
- beganTouchID: null,
42
- pressTimer: null,
39
+ _firstTouchInfo: null,
43
40
 
44
41
  touchesBegan: function(touches, event){
45
- if (this.began){
46
- return;
47
- }
48
- this.began = true;
49
42
  if (this._state === UIGestureRecognizer.State.possible){
50
- if (touches.length === 1){
51
- this.beganTouchID = touches[0].identifier;
52
- this.beganLocation = touches[0].locationInView(this.view);
53
- this.pressTimer = JSTimer.scheduledTimerWithInterval(this.minimumPressInterval, this.minimumTimeReached, this);
43
+ if (touches.length === 1 && event.touches.length === 1){
44
+ var touch = touches[0];
45
+ this._firstTouchInfo = {
46
+ identifier: touch.identifier,
47
+ location: touch.locationInWindow,
48
+ timer: JSTimer.scheduledTimerWithInterval(this.minimumPressInterval, this.minimumTimeReached, this)
49
+ };
54
50
  this._setState(UIGestureRecognizer.State.began);
55
51
  }
56
52
  }else{
57
- this._setState(UIGestureRecognizer.State.failed);
53
+ this.end(UIGestureRecognizer.State.failed);
58
54
  }
59
55
  },
60
56
 
61
57
  minimumTimeReached: function(timer){
58
+ this._firstTouchInfo = null;
62
59
  this._setState(UIGestureRecognizer.State.recognized);
63
- this.pressTimer = null;
64
60
  },
65
61
 
66
62
  end: function(state){
67
- if (this.pressTimer !== null){
68
- this.pressTimer.invalidate();
69
- this.pressTimer = null;
63
+ if (this._firstTouchInfo !== null){
64
+ if (this._firstTouchInfo.timer !== null){
65
+ this._firstTouchInfo.timer.invalidate();
66
+ }
67
+ this._firstTouchInfo = null;
70
68
  }
71
- this._setState(UIGestureRecognizer.State.failed);
69
+ this._setState(state);
72
70
  },
73
71
 
74
72
  touchesMoved: function(touches, event){
75
- if (this._state === UIGestureRecognizer.State.possible){
73
+ if (this._firstTouchInfo === null){
76
74
  return;
77
75
  }
78
- var touch = event.touchForIdentifier(this.beganTouchID);
79
- if (touch === null){
80
- this.end(UIGestureRecognizer.State.failed);
76
+ var touch = event.touchForIdentifier(this._firstTouchInfo.identifier);
77
+ if (touches.indexOf(touch) < 0){
81
78
  return;
82
79
  }
83
80
  var location = touch.locationInView(this.view);
@@ -88,26 +85,22 @@ JSClass("UIPressGestureRecognizer", UIGestureRecognizer, {
88
85
  },
89
86
 
90
87
  touchesEnded: function(touches, event){
91
- var beganTouchID = this.beganTouchID;
92
- this.began = false;
93
- this.beganLocation = null;
94
- this.beganTouchID = null;
95
- if (this._state === UIGestureRecognizer.State.possible){
88
+ if (this._firstTouchInfo === null){
96
89
  return;
97
90
  }
98
- var touch = event.touchForIdentifier(beganTouchID);
99
- if (touch === null){
100
- this.end(UIGestureRecognizer.State.failed);
91
+ var touch = event.touchForIdentifier(this._firstTouchInfo.identifier);
92
+ if (touches.indexOf(touch) < 0){
101
93
  return;
102
94
  }
103
95
  this.end(UIGestureRecognizer.State.cancled);
104
96
  },
105
97
 
106
98
  touchesCanceled: function(touches, event){
107
- this.began = false;
108
- this.beganLocation = null;
109
- this.beganTouchID = null;
110
- if (this._state === UIGestureRecognizer.State.possible){
99
+ if (this._firstTouchInfo === null){
100
+ return;
101
+ }
102
+ var touch = event.touchForIdentifier(this._firstTouchInfo.identifier);
103
+ if (touches.indexOf(touch) < 0){
111
104
  return;
112
105
  }
113
106
  this.end(UIGestureRecognizer.State.failed);
@@ -48,7 +48,7 @@ JSClass("UIScrollGestureRecognizer", UIGestureRecognizer, {
48
48
  var touch = touches[0];
49
49
  var location = touch.locationInWindow;
50
50
  this._touchTracking = {
51
- identifier: touches[0],
51
+ identifier: touch.identifier,
52
52
  startingLocation: JSPoint(location),
53
53
  location: location,
54
54
  contentOffset: JSPoint(this.contentOffset),
@@ -80,9 +80,12 @@ JSClass("UIScrollGestureRecognizer", UIGestureRecognizer, {
80
80
  if (!this._scrollsVertically && !this._scrollsHorizontally){
81
81
  return;
82
82
  }
83
- if (this._touchTracking === null){
84
- this._beginTrackingTouches(touches, event);
83
+ if (this._touchTracking !== null){
84
+ if (event.touchForIdentifier(this._touchTracking.identifier) !== null){
85
+ return;
86
+ }
85
87
  }
88
+ this._beginTrackingTouches(touches, event);
86
89
  },
87
90
 
88
91
  touchesMoved: function(touches, event){
@@ -96,8 +99,8 @@ JSClass("UIScrollGestureRecognizer", UIGestureRecognizer, {
96
99
  }
97
100
  }
98
101
  var touch = event.touchForIdentifier(this._touchTracking.identifier);
99
- if (touch === null){
100
- touch = touches[0];
102
+ if (touches.indexOf(touch) < 0){
103
+ return;
101
104
  }
102
105
  var location = touch.locationInWindow;
103
106
  var delta = location.subtracting(this._touchTracking.startingLocation);
@@ -133,6 +136,13 @@ JSClass("UIScrollGestureRecognizer", UIGestureRecognizer, {
133
136
  if (!this._scrollsVertically && !this._scrollsHorizontally){
134
137
  return;
135
138
  }
139
+ if (this._touchTracking === null){
140
+ return;
141
+ }
142
+ var touch = event.touchForIdentifier(this._touchTracking.identifier);
143
+ if (touches.indexOf(touch) < 0){
144
+ return;
145
+ }
136
146
  var dt = event.timestamp - this._touchTracking.timestamp;
137
147
  if (dt < 0.05){
138
148
  this._beginCoasting(this._touchTracking.velocity);
@@ -146,6 +156,13 @@ JSClass("UIScrollGestureRecognizer", UIGestureRecognizer, {
146
156
  if (!this._scrollsVertically && !this._scrollsHorizontally){
147
157
  return;
148
158
  }
159
+ if (this._touchTracking === null){
160
+ return;
161
+ }
162
+ var touch = event.touchForIdentifier(this._touchTracking.identifier);
163
+ if (touches.indexOf(touch) < 0){
164
+ return;
165
+ }
149
166
  this._endTrackingTouches();
150
167
  this._setState(UIGestureRecognizer.State.ended);
151
168
  },
@@ -555,7 +555,7 @@ JSClass('UIScrollView', UIView, {
555
555
  var touch = touches[0];
556
556
  var location = touch.locationInView(this);
557
557
  this._touchTracking = {
558
- identifier: touches[0],
558
+ identifier: touch.identifier,
559
559
  startingLocation: JSPoint(location),
560
560
  location: location,
561
561
  contentOffset: JSPoint(this.contentOffset),
@@ -586,6 +586,11 @@ JSClass('UIScrollView', UIView, {
586
586
  if (!this._scrollsVertically && !this._scrollsHorizontally){
587
587
  return UIScrollView.$super.touchesBegan.call(this, touches, event);
588
588
  }
589
+ if (this._touchTracking !== null){
590
+ if (event.touchForIdentifier(this._touchTracking.identifier) !== null){
591
+ return;
592
+ }
593
+ }
589
594
  this._beginTrackingTouches(touches, event);
590
595
  },
591
596
 
@@ -597,8 +602,8 @@ JSClass('UIScrollView', UIView, {
597
602
  this._beginTrackingTouches(touches, event);
598
603
  }
599
604
  var touch = event.touchForIdentifier(this._touchTracking.identifier);
600
- if (touch === null){
601
- touch = touches[0];
605
+ if (touches.indexOf(touch) < 0){
606
+ return;
602
607
  }
603
608
  var location = touch.locationInView(this);
604
609
  var delta = location.subtracting(this._touchTracking.startingLocation);
@@ -623,6 +628,13 @@ JSClass('UIScrollView', UIView, {
623
628
  if (!this._scrollsVertically && !this._scrollsHorizontally){
624
629
  return UIScrollView.$super.touchesEnded.call(this, touches, event);
625
630
  }
631
+ if (this._touchTracking === null){
632
+ return;
633
+ }
634
+ var touch = event.touchForIdentifier(this._touchTracking.identifier);
635
+ if (touches.indexOf(touch) < 0){
636
+ return;
637
+ }
626
638
  var dt = event.timestamp - this._touchTracking.timestamp;
627
639
  if (dt < 0.05){
628
640
  this._beginCoasting(this._touchTracking.velocity);
@@ -634,6 +646,13 @@ JSClass('UIScrollView', UIView, {
634
646
  if (!this._scrollsVertically && !this._scrollsHorizontally){
635
647
  return UIScrollView.$super.touchesCanceled.call(this, touches, event);
636
648
  }
649
+ if (this._touchTracking === null){
650
+ return;
651
+ }
652
+ var touch = event.touchForIdentifier(this._touchTracking.identifier);
653
+ if (touches.indexOf(touch) < 0){
654
+ return;
655
+ }
637
656
  this._endTrackingTouches();
638
657
  },
639
658
 
@@ -20,65 +20,60 @@ JSClass("UITapGestureRecognizer", UIGestureRecognizer, {
20
20
 
21
21
  // MARK: - Events
22
22
 
23
- began: false,
24
- beganLocation: null,
25
- beganTouchID: null,
23
+ _firstTouchInfo: null,
26
24
 
27
25
  touchesBegan: function(touches, event){
28
- if (this.began){
29
- return;
30
- }
31
- this.began = true;
32
26
  if (this._state === UIGestureRecognizer.State.possible){
33
- if (touches.length === 1){
34
- this.beganTouchID = touches[0].identifier;
35
- this.beganLocation = touches[0].locationInView(this.view);
27
+ if (touches.length === 1 && event.touches.length === 1){
28
+ var touch = touches[0];
29
+ this._firstTouchInfo = {
30
+ identifier: touch.identifier,
31
+ location: JSPoint(touch.locationInWindow)
32
+ };
36
33
  this._setState(UIGestureRecognizer.State.began);
37
34
  }
38
35
  }else{
36
+ this._firstTouchInfo = null;
39
37
  this._setState(UIGestureRecognizer.State.failed);
40
38
  }
41
39
  },
42
40
 
43
41
  touchesMoved: function(touches, event){
44
- if (this._state === UIGestureRecognizer.State.possible){
42
+ if (this._firstTouchInfo === null){
45
43
  return;
46
44
  }
47
- var touch = event.touchForIdentifier(this.beganTouchID);
48
- if (touch === null){
49
- this._setState(UIGestureRecognizer.State.failed);
45
+ var touch = event.touchForIdentifier(this._firstTouchInfo.identifier);
46
+ if (touches.indexOf(touch) < 0){
50
47
  return;
51
48
  }
52
- var location = touch.locationInView(this.view);
53
- var distance = location.distanceToPoint(this.beganLocation);
49
+ var distance = touch.locationInWindow.distanceToPoint(this._firstTouchInfo.location);
54
50
  if (distance > 10){
51
+ this._firstTouchInfo = null;
55
52
  this._setState(UIGestureRecognizer.State.failed);
56
53
  }
57
54
  },
58
55
 
59
56
  touchesEnded: function(touches, event){
60
- var beganTouchID = this.beganTouchID;
61
- this.began = false;
62
- this.beganLocation = null;
63
- this.beganTouchID = null;
64
- if (this._state === UIGestureRecognizer.State.possible){
57
+ if (this._firstTouchInfo === null){
65
58
  return;
66
59
  }
67
- var touch = event.touchForIdentifier(beganTouchID);
68
- if (touch === null){
69
- this._setState(UIGestureRecognizer.State.failed);
60
+ var touch = event.touchForIdentifier(this._firstTouchInfo.identifier);
61
+ if (touches.indexOf(touch) < 0){
70
62
  return;
71
63
  }
64
+ this._firstTouchInfo = null;
72
65
  this._setState(UIGestureRecognizer.State.recognized);
73
66
  },
74
67
 
75
68
  touchesCanceled: function(touches, event){
76
- this.began = false;
77
- this.beganLocation = null;
78
- this.beganTouchID = null;
79
- if (this._state === UIGestureRecognizer.State.possible){
69
+ if (this._firstTouchInfo === null){
70
+ return;
71
+ }
72
+ var touch = event.touchForIdentifier(this._firstTouchInfo.identifier);
73
+ if (touches.indexOf(touch) < 0){
80
74
  return;
81
75
  }
76
+ this._firstTouchInfo = null;
82
77
  this._setState(UIGestureRecognizer.State.failed);
83
78
  }
84
79
 
@@ -1028,21 +1028,22 @@ JSClass('UIWindow', UIView, {
1028
1028
  }
1029
1029
  },
1030
1030
 
1031
+ _hadModalWhenTouchesBegan: false,
1032
+
1031
1033
  _sendTouchEvent: function(event){
1032
1034
  var modal = this._modal;
1033
1035
  while (modal !== null && modal._modal !== null){
1034
1036
  modal = modal._modal;
1035
1037
  }
1036
1038
  var i, l;
1039
+ if (event.type === UIEvent.Type.touchesBegan){
1040
+ if (!event.hasPastTouches()){
1041
+ this._hadModalWhenTouchesBegan = modal !== null;
1042
+ }
1043
+ }
1037
1044
  if (modal !== null){
1038
1045
  if (event.type == UIEvent.Type.touchesEnded){
1039
- var activeTouchCount = 0;
1040
- for (i = 0, l = event.touches.length; i < l; ++i){
1041
- if (event.touches[i].phase !== UITouch.Phase.ended && event.touches[i].phase !== UITouch.Phase.canceled){
1042
- ++activeTouchCount;
1043
- }
1044
- }
1045
- if (modal._isOpen && activeTouchCount === 0){
1046
+ if (modal._isOpen && !event.hasFutureTouches() && this._hadModalWhenTouchesBegan){
1046
1047
  modal.makeKeyAndOrderFront();
1047
1048
  modal.indicateModalStatus();
1048
1049
  }
@@ -1052,55 +1053,72 @@ JSClass('UIWindow', UIView, {
1052
1053
  var j, k;
1053
1054
  // We only dispatch the touches that changed in this version of the event.
1054
1055
  // A view can get all the touches it wants from the event.
1055
- var touches = event.changedTouchesInWindow(this);
1056
- if (touches.length === 0){
1056
+ var changedTouches = event.changedTouchesInWindow(this);
1057
+ if (changedTouches.length === 0){
1057
1058
  return;
1058
1059
  }
1059
1060
  var touch;
1060
1061
  var view;
1061
- var touchesByView = {};
1062
- for (i = 0, l = touches.length; i < l; ++i){
1063
- touch = touches[i];
1062
+ var changedTouchesByView = {};
1063
+ for (i = 0, l = changedTouches.length; i < l; ++i){
1064
+ touch = changedTouches[i];
1064
1065
  if (touch.view){
1065
- if (!touchesByView[touch.view.objectID]){
1066
- touchesByView[touch.view.objectID] = [];
1066
+ if (!changedTouchesByView[touch.view.objectID]){
1067
+ changedTouchesByView[touch.view.objectID] = [];
1067
1068
  }
1068
- touchesByView[touch.view.objectID].push(touch);
1069
+ changedTouchesByView[touch.view.objectID].push(touch);
1069
1070
  }
1070
1071
  }
1071
1072
  if (event.type === UIEvent.Type.touchesBegan){
1072
- for (i = 0, l = touches.length; i < l; ++i){
1073
- touch = touches[i];
1073
+ var allTouches = event.touches;
1074
+ var allTouchesByView = {};
1075
+ for (i = 0, l = allTouches.length; i < l; ++i){
1076
+ touch = allTouches[i];
1077
+ if (touch.view){
1078
+ if (!allTouchesByView[touch.view.objectID]){
1079
+ allTouchesByView[touch.view.objectID] = [];
1080
+ }
1081
+ allTouchesByView[touch.view.objectID].push(touch);
1082
+ }
1083
+ }
1084
+ for (i = 0, l = changedTouches.length; i < l; ++i){
1085
+ touch = changedTouches[i];
1074
1086
  if (touch.view !== null){
1075
1087
  logger.warn("beginning touch that already has a view");
1076
1088
  continue;
1077
1089
  }
1078
1090
  view = this.hitTest(touch.locationInWindow) || this;
1079
- if (!touchesByView[view.objectID]){
1080
- touchesByView[view.objectID] = [];
1081
- }
1082
- if (view.isMultipleTouchEnabled || touchesByView[view.objectID].length === 0){
1091
+ // For views that don't support multiple touch, only the first
1092
+ // seen touch will be associated with the view. If a touch isn't
1093
+ // associated with a view here on touchesBegan, the touch will
1094
+ // never be sent to any view for any future event.
1095
+ if (view.isMultipleTouchEnabled || !allTouchesByView[view.objectID]){
1096
+ allTouchesByView[view.objectID] = [];
1097
+ if (!changedTouchesByView[view.objectID]){
1098
+ changedTouchesByView[view.objectID] = [];
1099
+ }
1083
1100
  touch.view = view;
1084
- touchesByView[view.objectID].push(touch);
1101
+ changedTouchesByView[view.objectID].push(touch);
1102
+ allTouchesByView[view.objectID].push(touch);
1085
1103
  }
1086
1104
  }
1087
1105
  }
1088
- for (var id in touchesByView){
1089
- touches = touchesByView[id];
1090
- view = touches[0].view;
1106
+ for (var id in changedTouchesByView){
1107
+ changedTouches = changedTouchesByView[id];
1108
+ view = changedTouches[0].view;
1091
1109
  if (view.window === this){
1092
1110
  switch (event.type){
1093
1111
  case UIEvent.Type.touchesBegan:
1094
- view.touchesBegan(touches, event);
1112
+ view.touchesBegan(changedTouches, event);
1095
1113
  break;
1096
1114
  case UIEvent.Type.touchesMoved:
1097
- view.touchesMoved(touches, event);
1115
+ view.touchesMoved(changedTouches, event);
1098
1116
  break;
1099
1117
  case UIEvent.Type.touchesCanceled:
1100
- view.touchesCanceled(touches, event);
1118
+ view.touchesCanceled(changedTouches, event);
1101
1119
  break;
1102
1120
  case UIEvent.Type.touchesEnded:
1103
- view.touchesEnded(touches, event);
1121
+ view.touchesEnded(changedTouches, event);
1104
1122
  break;
1105
1123
  }
1106
1124
  }
@@ -850,7 +850,7 @@ JSClass("UIWindowServer", JSObject, {
850
850
 
851
851
  activeTouchEvent: null,
852
852
 
853
- createTouchEvent: function(type, timestamp, changedTouchDescriptors){
853
+ createTouchEvent: function(type, timestamp, changedTouchDescriptors, touchIdentifiers){
854
854
  var window;
855
855
  var touch;
856
856
  var descriptor;
@@ -858,6 +858,15 @@ JSClass("UIWindowServer", JSObject, {
858
858
  var i, l;
859
859
  var phase = this._touchPhaseForEventType(type);
860
860
 
861
+ if (this.activeTouchEvent !== null){
862
+ if (this.activeTouchEvent.removeUnreferencedTouches(touchIdentifiers) > 0){
863
+ logger.warn("removed unreferenced touches");
864
+ }
865
+ if (this.activeTouchEvent.touches.length === 0){
866
+ this.activeTouchEvent = null;
867
+ }
868
+ }
869
+
861
870
  // Create or update the active touch event
862
871
  if (this.activeTouchEvent === null){
863
872
  if (type != UIEvent.Type.touchesBegan){
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2023.18.3
3
+ JSBundleVersion: 2023.19.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node": ">=10.10.0"
10
10
  },
11
11
  "name": "@breakside/jskit",
12
- "version": "2023.18.3",
12
+ "version": "2023.19.0",
13
13
  "license": "SEE LICENSE IN LICENSE.txt",
14
14
  "files": [
15
15
  "*"