@breakside/jskit 2025.24.0 → 2025.27.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/io.breakside.JSKit.Foundation-bundle.js +2 -2
  7. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  8. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  9. package/Info.json +2 -2
  10. package/Node/io.breakside.jskit-bundle.js +2 -2
  11. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  12. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  13. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  14. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  15. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  16. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  17. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  18. package/Root/Frameworks/DOM/Info.yaml +1 -1
  19. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  20. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  21. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  22. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  23. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  24. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeAtom.js +3 -1
  25. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeEdit.js +28 -0
  26. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeEditList.js +60 -0
  27. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeMediaInformation.js +8 -0
  28. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeMovieHeader.js +1 -1
  29. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeSampleDescription.js +1 -1
  30. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeTrack.js +2 -0
  31. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeTrackHeader.js +2 -2
  32. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeVideoMediaInformationHeader.js +59 -0
  33. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  34. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  35. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  36. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  37. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  38. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  39. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  40. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  41. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  42. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  43. package/Root/Frameworks/UIKit/UICursor.js +8 -0
  44. package/Root/Frameworks/UIKit/UIPopupWindow.js +177 -8
  45. package/Root/Frameworks/UIKit/UIWindow.js +26 -3
  46. package/Root/Frameworks/UIKit/UIWindowServer.js +252 -13
  47. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  48. package/package.json +1 -1
@@ -153,6 +153,10 @@ UICursor.SystemIdentifier = {
153
153
  operationNotAllowed: 'not-allowed',
154
154
  resizeLeftRight: 'col-resize',
155
155
  resizeUpDown: 'row-resize',
156
+ resizeEastWest: 'ew-resize',
157
+ resizeNorthSouth: 'ns-resize',
158
+ resizeNorthEastSouthWest: 'nesw-resize',
159
+ resizeNorthWestSouthEast: 'nwse-resize',
156
160
  openHand: 'grab',
157
161
  closedHand: 'grabbing',
158
162
  dragLink: 'alias',
@@ -167,6 +171,10 @@ UICursor.pointingHand = UICursor.initWithSystemIdentifier(UICursor.SystemIdentif
167
171
  UICursor.operationNotAllowed = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.operationNotAllowed);
168
172
  UICursor.resizeLeftRight = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.resizeLeftRight);
169
173
  UICursor.resizeUpDown = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.resizeUpDown);
174
+ UICursor.resizeEastWest = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.resizeEastWest);
175
+ UICursor.resizeNorthSouth = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.resizeNorthSouth);
176
+ UICursor.resizeNorthEastSouthWest = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.resizeNorthEastSouthWest);
177
+ UICursor.resizeNorthWestSouthEast = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.resizeNorthWestSouthEast);
170
178
  UICursor.openHand = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.openHand);
171
179
  UICursor.closedHand = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.closedHand);
172
180
  UICursor.dragLink = UICursor.initWithSystemIdentifier(UICursor.SystemIdentifier.dragLink);
@@ -23,6 +23,7 @@ JSClass("UIPopupWindow", UIWindow, {
23
23
  showsSourceArrow: JSDynamicProperty('_showsSourceArrow', false),
24
24
  sourceArrowSize: JSDynamicProperty('_sourceArrowSize', 10),
25
25
  sourceSpacing: JSDynamicProperty('_sourceSpacing', 0),
26
+ sourceView: null,
26
27
  isUserMovable: false,
27
28
  placement: 0,
28
29
  canBecomeKey: true,
@@ -41,8 +42,59 @@ JSClass("UIPopupWindow", UIWindow, {
41
42
  },
42
43
 
43
44
  setShowsSourceArrow: function(showsSourceArrow){
45
+ if (showsSourceArrow === this._showsSourceArrow){
46
+ return;
47
+ }
48
+ if (this._isOpen){
49
+ var frame = JSRect(this.untransformedFrame);
50
+ if (this.placement === UIPopupWindow.Placement.left){
51
+ if (this._showsSourceArrow){
52
+ frame.size.width -= this._actualArrowSize;
53
+ }else{
54
+ frame.size.width += this._actualArrowSize;
55
+ }
56
+ }else if (this.placement === UIPopupWindow.Placement.right){
57
+ if (this._showsSourceArrow){
58
+ frame.size.width -= this._actualArrowSize;
59
+ frame.origin.x += this._actualArrowSize;
60
+ if (this._downLocation !== null){
61
+ this._downLocation.x -= this._actualArrowSize;
62
+ }
63
+ }else{
64
+ frame.size.width += this._actualArrowSize;
65
+ frame.origin.x -= this._actualArrowSize;
66
+ if (this._downLocation !== null){
67
+ this._downLocation.x += this._actualArrowSize;
68
+ }
69
+ }
70
+ }else if (this.placement === UIPopupWindow.Placement.above){
71
+ if (this._showsSourceArrow){
72
+ frame.size.height -= this._actualArrowSize;
73
+ }else{
74
+ frame.size.height += this._actualArrowSize;
75
+ }
76
+ }else if (this.placement === UIPopupWindow.Placement.below){
77
+ if (this._showsSourceArrow){
78
+ frame.size.height -= this._actualArrowSize;
79
+ frame.origin.y += this._actualArrowSize;
80
+ if (this._downLocation !== null){
81
+ this._downLocation.y -= this._actualArrowSize;
82
+ }
83
+ }else{
84
+ frame.size.height += this._actualArrowSize;
85
+ frame.origin.y -= this._actualArrowSize;
86
+ if (this._downLocation !== null){
87
+ this._downLocation.x += this._actualArrowSize;
88
+ }
89
+ }
90
+ }
91
+ this.untransformedFrame = frame;
92
+ }
44
93
  this._showsSourceArrow = showsSourceArrow;
45
94
  this._styler.updateWindow(this);
95
+ if (this._isOpen && !this._showsSourceArrow){
96
+ JSNotificationCenter.shared.post("UIPopupWindowDidDetachFromSource", this);
97
+ }
46
98
  },
47
99
 
48
100
  setSourceArrowSize: function(sourceArrowSize){
@@ -68,7 +120,7 @@ JSClass("UIPopupWindow", UIWindow, {
68
120
  animated = true;
69
121
  }
70
122
  var sourceFrame = view.convertRectToScreen(view.bounds).rectWithInsets(-this._sourceSpacing);
71
- var safeFrame = view.window.screen.availableFrame;
123
+ var safeFrame = view.window.screen.availableFrame.rectWithInsets(20);
72
124
 
73
125
  // Size to our content's preferred size
74
126
  this.sizeToFit();
@@ -153,8 +205,8 @@ JSClass("UIPopupWindow", UIWindow, {
153
205
  if (frame.origin.x + frame.size.width > safeFrame.origin.x + safeFrame.size.width){
154
206
  frame.origin.x = safeFrame.origin.x + safeFrame.size.width - frame.size.width;
155
207
  }
156
- if (frame.origin.x < 0){
157
- frame.origin.x = 0;
208
+ if (frame.origin.x < safeFrame.origin.x){
209
+ frame.origin.x = safeFrame.origin.x;
158
210
  if (frame.size.width > safeFrame.size.width){
159
211
  frame.size.width = safeFrame.size.width;
160
212
  }
@@ -164,8 +216,8 @@ JSClass("UIPopupWindow", UIWindow, {
164
216
  if (frame.origin.y + frame.size.height > safeFrame.origin.y + safeFrame.size.height){
165
217
  frame.origin.y = safeFrame.origin.y + safeFrame.size.height - frame.size.height;
166
218
  }
167
- if (frame.origin.y < 0){
168
- frame.origin.y = 0;
219
+ if (frame.origin.y < safeFrame.origin.y){
220
+ frame.origin.y = safeFrame.origin.y;
169
221
  if (frame.size.height > safeFrame.size.height){
170
222
  frame.size.height = safeFrame.size.height;
171
223
  }
@@ -216,6 +268,7 @@ JSClass("UIPopupWindow", UIWindow, {
216
268
 
217
269
  this.placement = placement;
218
270
  this.frame = frame;
271
+ this.sourceView = view;
219
272
 
220
273
  // Create animated opening, closing
221
274
  if (animated){
@@ -241,12 +294,96 @@ JSClass("UIPopupWindow", UIWindow, {
241
294
  this.makeKeyAndOrderFront();
242
295
  },
243
296
 
297
+ repositionSourceArrow: function(){
298
+ var view = this.sourceView;
299
+ if (view === null){
300
+ return;
301
+ }
302
+ var sourceFrame = view.convertRectToScreen(view.bounds);
303
+ var frame = this.untransformedFrame;
304
+ if (sourceFrame === null){
305
+ this.sourceView = null;
306
+ this.showsSourceArrow = false;
307
+ return;
308
+ }
309
+ var x, y;
310
+ var minY = frame.origin.y + this.styler.cornerRadius + this._actualArrowSize;
311
+ var maxY = frame.origin.y + frame.size.height - this.styler.cornerRadius - this._actualArrowSize;
312
+ var minX = frame.origin.x + this.styler.cornerRadius + this._actualArrowSize;
313
+ var maxX = frame.origin.x + frame.size.width - this.styler.cornerRadius - this._actualArrowSize;
314
+ if (this.placement === UIPopupWindow.Placement.left){
315
+ x = sourceFrame.origin.x - this._sourceSpacing;
316
+ if (Math.abs(frame.origin.x + frame.size.width - x) < 1){
317
+ y = sourceFrame.center.y;
318
+ if (y >= minY && y <= maxY){
319
+ this.anchorPoint = JSPoint(1, (y - frame.origin.y) / frame.size.height);
320
+ this.untransformedFrame = frame;
321
+ this.setNeedsLayout();
322
+ }else{
323
+ this.sourceView = null;
324
+ this.showsSourceArrow = false;
325
+ }
326
+ }else{
327
+ this.sourceView = null;
328
+ this.showsSourceArrow = false;
329
+ }
330
+ }else if (this.placement === UIPopupWindow.Placement.right){
331
+ x = sourceFrame.origin.x + sourceFrame.size.width + this._sourceSpacing;
332
+ if (Math.abs(frame.origin.x - x) < 1){
333
+ y = sourceFrame.center.y;
334
+ if (y >= minY && y <= maxY){
335
+ this.anchorPoint = JSPoint(0, (y - frame.origin.y) / frame.size.height);
336
+ this.untransformedFrame = frame;
337
+ this.setNeedsLayout();
338
+ }else{
339
+ this.sourceView = null;
340
+ this.showsSourceArrow = false;
341
+ }
342
+ }else{
343
+ this.sourceView = null;
344
+ this.showsSourceArrow = false;
345
+ }
346
+ }else if (this.placement === UIPopupWindow.Placement.above){
347
+ y = sourceFrame.origin.y - this._sourceSpacing;
348
+ if (Math.abs(frame.origin.y + frame.size.height - y) < 1){
349
+ x = sourceFrame.center.x;
350
+ if (x >= minX && x <= maxX){
351
+ this.anchorPoint = JSPoint((x - frame.origin.x) / frame.size.width, 1);
352
+ this.untransformedFrame = frame;
353
+ this.setNeedsLayout();
354
+ }else{
355
+ this.sourceView = null;
356
+ this.showsSourceArrow = false;
357
+ }
358
+ }else{
359
+ this.sourceView = null;
360
+ this.showsSourceArrow = false;
361
+ }
362
+ }else if (this.placement === UIPopupWindow.Placement.below){
363
+ y = sourceFrame.origin.y + sourceFrame.size.height + this._sourceSpacing;
364
+ if (Math.abs(frame.origin.y - y) < 1){
365
+ x = sourceFrame.center.x;
366
+ if (x >= minX && x <= maxX){
367
+ this.anchorPoint = JSPoint((x - frame.origin.x) / frame.size.width, 0);
368
+ this.untransformedFrame = frame;
369
+ this.setNeedsLayout();
370
+ }else{
371
+ this.sourceView = null;
372
+ this.showsSourceArrow = false;
373
+ }
374
+ }else{
375
+ this.sourceView = null;
376
+ this.showsSourceArrow = false;
377
+ }
378
+ }
379
+ },
380
+
244
381
  openCenteredInView: function(view, animated){
245
382
  if (animated === undefined){
246
383
  animated = true;
247
384
  }
248
385
  var sourceFrame = view.convertRectToScreen(view.bounds);
249
- var safeFrame = view.window.screen.availableFrame;
386
+ var safeFrame = view.window.screen.availableFrame.rectWithInsets(20);
250
387
 
251
388
  this.sizeToFit();
252
389
  var frame = JSRect(this.frame);
@@ -281,9 +418,12 @@ JSClass("UIPopupWindow", UIWindow, {
281
418
  this.closeAnimator = closeAnimator;
282
419
  }
283
420
  }
284
-
285
421
  this.makeKeyAndOrderFront();
422
+ },
286
423
 
424
+ close: function(){
425
+ UIPopupWindow.$super.close.call(this);
426
+ this.sourceView = null;
287
427
  },
288
428
 
289
429
  modalIndicationClosesWindow: false,
@@ -300,7 +440,33 @@ JSClass("UIPopupWindow", UIWindow, {
300
440
  UIPopupWindow.$super.indicateModalStatus.call(this);
301
441
  },
302
442
 
303
- accessibilityRole: UIAccessibility.Role.popover
443
+ accessibilityRole: UIAccessibility.Role.popover,
444
+
445
+ minimumMoveDistance: 10,
446
+
447
+ mouseDragged: function(event){
448
+ if (this._showsSourceArrow && this._isMoving){
449
+ var frameBeforeMoving = this.frame;
450
+ var location = this.convertPointToScreen(event.locationInWindow);
451
+ var distance = this._downLocation ? location.distanceToPoint(this._downLocation) : JSPoint.Zero;
452
+ UIPopupWindow.$super.mouseDragged.call(this, event);
453
+ this._didMove = distance >= this.minimumMoveDistance;
454
+ if (this._didMove){
455
+ this.showsSourceArrow = false;
456
+ }else{
457
+ this.frame = frameBeforeMoving;
458
+ }
459
+ }else{
460
+ UIPopupWindow.$super.mouseDragged.call(this, event);
461
+ }
462
+ },
463
+
464
+ _windowServerDidResize: function(){
465
+ UIPopupWindow.$super._windowServerDidResize.call(this);
466
+ if (this._showsSourceArrow){
467
+ this.repositionSourceArrow();
468
+ }
469
+ },
304
470
 
305
471
  });
306
472
 
@@ -428,6 +594,9 @@ JSClass("UIPopupWindowStyler", UIWindowStyler, {
428
594
  popupArrow.position = anchorPosition;
429
595
  popupArrow.anchorPoint = JSPoint(0.5, 0);
430
596
  }
597
+ window._resizeView = popupBacking;
598
+ }else{
599
+ window._resizeView = null;
431
600
  }
432
601
  window._contentView.frame = window.bounds.rectWithInsets(contentInsets);
433
602
  },
@@ -327,6 +327,9 @@ JSClass('UIWindow', UIView, {
327
327
  this._setTraitCollection(traits);
328
328
  }
329
329
  },
330
+
331
+ _windowServerDidResize: function(){
332
+ },
330
333
 
331
334
  traitCollection: JSReadOnlyProperty('_traitCollection', null),
332
335
 
@@ -417,6 +420,7 @@ JSClass('UIWindow', UIView, {
417
420
  if (!this._isOpen){
418
421
  return;
419
422
  }
423
+ JSNotificationCenter.shared.post("UIWindowWillClose", this);
420
424
  if (this.viewController){
421
425
  this.viewController.viewWillDisappear(false);
422
426
  }else if (this._contentViewController){
@@ -426,13 +430,14 @@ JSClass('UIWindow', UIView, {
426
430
  this.openAnimator.stopAndCallCompletions();
427
431
  }
428
432
  if (this.closeAnimator !== null){
429
- var self = this;
430
433
  this.closeAnimator.addCompletion(function(){
431
- self.windowServer.windowRemoved(self);
432
- });
434
+ this.windowServer.windowRemoved(this);
435
+ JSNotificationCenter.shared.post("UIWindowDidClose", this);
436
+ }, this);
433
437
  this.closeAnimator.start();
434
438
  }else{
435
439
  this.windowServer.windowRemoved(this);
440
+ JSNotificationCenter.shared.post("UIWindowDidClose", this);
436
441
  }
437
442
  this._isOpen = false;
438
443
  },
@@ -663,6 +668,24 @@ JSClass('UIWindow', UIView, {
663
668
  return responder;
664
669
  },
665
670
 
671
+ minimumSize: JSDynamicProperty("_minimumSize", null),
672
+ maximumSize: JSDynamicProperty("_maximumSize", null),
673
+ _canResizeWidth: false,
674
+ _canResizeHeight: false,
675
+ _resizeView: null,
676
+
677
+ setMinimumSize: function(minimumSize){
678
+ this._minimumSize = JSSize(minimumSize);
679
+ this._canResizeWidth = this._minimumSize !== null && this._maximumSize !== null && this._minimumSize.width !== this._maximumSize.width;
680
+ this._canResizeHeight = this._minimumSize !== null && this._maximumSize !== null && this._minimumSize.height !== this._maximumSize.height;
681
+ },
682
+
683
+ setMaximumSize: function(maximumSize){
684
+ this._maximumSize = JSSize(maximumSize);
685
+ this._canResizeWidth = this._minimumSize !== null && this._maximumSize !== null && this._minimumSize.width !== this._maximumSize.width;
686
+ this._canResizeHeight = this._minimumSize !== null && this._maximumSize !== null && this._minimumSize.height !== this._maximumSize.height;
687
+ },
688
+
666
689
  // -------------------------------------------------------------------------
667
690
  // MARK: - First Responder
668
691
 
@@ -595,6 +595,52 @@ JSClass("UIWindowServer", JSObject, {
595
595
  return;
596
596
  }
597
597
 
598
+ var event;
599
+ var targetWindow;
600
+ var locationInWindow;
601
+
602
+ // window resizing is handled by the window server itself, rather than
603
+ // passing events to windows
604
+ if (this._windowResizeWindow !== null && this._windowResizeMouseEventData === null && type === UIEvent.Type.leftMouseDown && this.mouseDownCount === 0){
605
+ locationInWindow = this._windowResizeWindow.convertPointFromScreen(location);
606
+ var resizeOperation = this.windowResizeHitTest(this._windowResizeWindow, locationInWindow);
607
+ if (resizeOperation !== UIWindowServer.ResizeOperation.none){
608
+ this._mouseIdleTimer.invalidate();
609
+ if (this._tooltipWindow !== null){
610
+ this.hideTooltip();
611
+ }
612
+ this._leftClickCount = 1;
613
+ this._rightClickCount = 0;
614
+ this.mouseDownCount = 1;
615
+ this.mouseEventWindow = null;
616
+ this._previousMouseEventWindow = null;
617
+ this._windowResizeMouseEventData = {
618
+ operation: resizeOperation,
619
+ location0: JSPoint(location)
620
+ };
621
+ }else{
622
+ if (this._windowResizeCursor !== null){
623
+ this._windowResizeCursor.pop();
624
+ this._windowResizeCursor = null;
625
+ }
626
+ this._windowResizeWindow = null;
627
+ }
628
+ }
629
+ if (this._windowResizeMouseEventData !== null){
630
+ if (locationInWindow === undefined || locationInWindow === null){
631
+ locationInWindow = this._windowResizeWindow.convertPointFromScreen(location);
632
+ }
633
+ event = UIEvent.initMouseEventWithType(type, timestamp, this._windowResizeWindow, locationInWindow, modifiers, this._leftClickCount);
634
+ this.handleWindowResizeMouseEvent(event, location);
635
+ if (type === UIEvent.Type.leftMouseUp){
636
+ this._leftClickCount = 0;
637
+ this.mouseDownCount = 0;
638
+ this._windowResizeMouseEventData = null;
639
+ this.sendMouseTrackingEvents(timestamp, modifiers);
640
+ }
641
+ return;
642
+ }
643
+
598
644
  if (isADown){
599
645
  this._mouseIdleTimer.invalidate();
600
646
  if (this._tooltipWindow !== null){
@@ -643,8 +689,7 @@ JSClass("UIWindowServer", JSObject, {
643
689
  break;
644
690
  }
645
691
 
646
- var event;
647
- var targetWindow = this.mouseEventWindow;
692
+ targetWindow = this.mouseEventWindow;
648
693
 
649
694
  if (isAnUp){
650
695
  --this.mouseDownCount;
@@ -664,7 +709,8 @@ JSClass("UIWindowServer", JSObject, {
664
709
  }
665
710
  }
666
711
  if (targetWindow !== null){
667
- event = UIEvent.initMouseEventWithType(type, timestamp, targetWindow, targetWindow.convertPointFromScreen(location), modifiers, clickCount);
712
+ locationInWindow = targetWindow.convertPointFromScreen(location);
713
+ event = UIEvent.initMouseEventWithType(type, timestamp, targetWindow, locationInWindow, modifiers, clickCount);
668
714
  this._sendEventToApplication(event, targetWindow.application);
669
715
  }
670
716
  },
@@ -747,30 +793,211 @@ JSClass("UIWindowServer", JSObject, {
747
793
  _mouseTrackingWindow: null,
748
794
 
749
795
  sendMouseTrackingEvents: function(timestamp, modifiers){
750
- var window = null;
796
+ var mouseTrackingWindow = null;
797
+ var resizeWindow = null;
751
798
  var windowIndex;
799
+ var window;
752
800
  var location;
753
801
  var event;
754
802
  var hasWindowReceivingAllEvents = false;
755
- for (windowIndex = this.windowStack.length - 1; windowIndex >= 0 && window === null; --windowIndex){
756
- location = this.windowStack[windowIndex].convertPointFromScreen(this.mouseLocation);
757
- hasWindowReceivingAllEvents = hasWindowReceivingAllEvents || this.windowStack[windowIndex].receivesAllEvents;
758
- if (this.windowStack[windowIndex].userInteractionEnabled && this.windowStack[windowIndex].containsPoint(location)){
759
- window = this.windowStack[windowIndex];
803
+ var hasSeenMainWindow = false;
804
+ var resizeOperation = UIWindowServer.ResizeOperation.none;
805
+ for (windowIndex = this.windowStack.length - 1; windowIndex >= 0 && mouseTrackingWindow === null; --windowIndex){
806
+ window = this.windowStack[windowIndex];
807
+ if (!window.hidden){
808
+ location = window.convertPointFromScreen(this.mouseLocation);
809
+ hasWindowReceivingAllEvents = hasWindowReceivingAllEvents || window.receivesAllEvents;
810
+ if (window.userInteractionEnabled){
811
+ if (!hasSeenMainWindow){
812
+ resizeOperation = this.windowResizeHitTest(window, location);
813
+ }
814
+ if (resizeOperation !== UIWindowServer.ResizeOperation.none){
815
+ mouseTrackingWindow = window;
816
+ }else if (window.containsPoint(location)){
817
+ mouseTrackingWindow = window;
818
+ }
819
+ }
820
+ hasSeenMainWindow = hasSeenMainWindow || window === this.mainWindow;
760
821
  }
761
822
  }
762
- if (hasWindowReceivingAllEvents && window !== null && !window.receivesAllEvents){
763
- window = null;
823
+ if (hasWindowReceivingAllEvents && mouseTrackingWindow !== null && !mouseTrackingWindow.receivesAllEvents){
824
+ mouseTrackingWindow = null;
825
+ resizeOperation = UIWindowServer.ResizeOperation.none;
826
+ }
827
+ if (resizeOperation !== UIWindowServer.ResizeOperation.none){
828
+ resizeWindow = mouseTrackingWindow;
829
+ mouseTrackingWindow = null;
764
830
  }
765
831
  if (this._mouseTrackingWindow !== null){
766
- if (window !== this._mouseTrackingWindow){
832
+ if (mouseTrackingWindow !== this._mouseTrackingWindow){
767
833
  this._mouseTrackingWindow.sendMouseTrackingEvents(this._mouseTrackingWindow.convertPointFromScreen(this.mouseLocation), timestamp, modifiers, true);
768
834
  }
769
835
  }
770
- this._mouseTrackingWindow = window;
836
+ this._mouseTrackingWindow = mouseTrackingWindow;
771
837
  if (this._mouseTrackingWindow !== null){
772
838
  this._mouseTrackingWindow.sendMouseTrackingEvents(this._mouseTrackingWindow.convertPointFromScreen(this.mouseLocation), timestamp, modifiers, false);
773
839
  }
840
+ var resizeCursor = null;
841
+ if (resizeOperation !== UIWindowServer.ResizeOperation.none){
842
+ resizeCursor = this.cursorForWindowResizeOperation(resizeWindow, resizeOperation);
843
+ }
844
+ if (resizeCursor !== this._windowResizeCursor){
845
+ if (this._windowResizeCursor !== null){
846
+ this._windowResizeCursor.pop();
847
+ }
848
+ this._windowResizeCursor = resizeCursor;
849
+ if (this._windowResizeCursor !== null){
850
+ this._windowResizeCursor.push();
851
+ }
852
+ }
853
+ this._windowResizeWindow = resizeWindow;
854
+ },
855
+
856
+ _windowResizeCursor: null,
857
+ _windowResizeWindow: null,
858
+ _windowResizeMouseEventData: null,
859
+ _windowResizeWidthInside: 4,
860
+ _windowResizeWidthOutside: 4,
861
+
862
+ windowResizeHitTest: function(window, location){
863
+ if (!window._canResizeWidth && !window._canResizeHeight){
864
+ return UIWindowServer.ResizeOperation.none;
865
+ }
866
+ var resizeView = window;
867
+ if (window._resizeView !== null){
868
+ resizeView = window._resizeView;
869
+ location = window.convertPointToView(location, resizeView);
870
+ }
871
+ var resizeFrame = resizeView.bounds;
872
+ var cornerSize = Math.max(resizeView.cornerRadius, this._windowResizeWidthInside);
873
+ if (location.y < resizeFrame.origin.y - this._windowResizeWidthOutside){
874
+ return UIWindowServer.ResizeOperation.none;
875
+ }
876
+ if (location.x < resizeFrame.origin.x - this._windowResizeWidthOutside){
877
+ return UIWindowServer.ResizeOperation.none;
878
+ }
879
+ if (location.y > resizeFrame.origin.y + resizeFrame.size.height + this._windowResizeWidthOutside){
880
+ return UIWindowServer.ResizeOperation.none;
881
+ }
882
+ if (location.x > resizeFrame.origin.x + resizeFrame.size.width + this._windowResizeWidthOutside){
883
+ return UIWindowServer.ResizeOperation.none;
884
+ }
885
+ if (window._canResizeWidth && window._canResizeHeight){
886
+ if ((location.y <= resizeFrame.origin.y + cornerSize) && (location.x <= resizeFrame.origin.x + cornerSize)){
887
+ return UIWindowServer.ResizeOperation.topLeft;
888
+ }
889
+ if ((location.y <= resizeFrame.origin.y + cornerSize) && (location.x >= resizeFrame.origin.x + resizeFrame.size.width - cornerSize)){
890
+ return UIWindowServer.ResizeOperation.topRight;
891
+ }
892
+ if ((location.y >= resizeFrame.origin.y + resizeFrame.size.height - cornerSize) && (location.x >= resizeFrame.origin.x + resizeFrame.size.width - cornerSize)){
893
+ return UIWindowServer.ResizeOperation.bottomRight;
894
+ }
895
+ if ((location.y >= resizeFrame.origin.y + resizeFrame.size.height - cornerSize) && (location.x <= resizeFrame.origin.x + cornerSize)){
896
+ return UIWindowServer.ResizeOperation.bottomLeft;
897
+ }
898
+ }
899
+ if (window._canResizeWidth){
900
+ if (location.x <= resizeFrame.origin.x + this._windowResizeWidthInside){
901
+ return UIWindowServer.ResizeOperation.left;
902
+ }
903
+ if (location.x >= resizeFrame.origin.x + resizeFrame.size.width - this._windowResizeWidthInside){
904
+ return UIWindowServer.ResizeOperation.right;
905
+ }
906
+ }
907
+ if (window._canResizeHeight){
908
+ if (location.y <= resizeFrame.origin.y + this._windowResizeWidthInside){
909
+ return UIWindowServer.ResizeOperation.top;
910
+ }
911
+ if (location.y >= resizeFrame.origin.y + resizeFrame.size.height - this._windowResizeWidthInside){
912
+ return UIWindowServer.ResizeOperation.bottom;
913
+ }
914
+ }
915
+ return UIWindowServer.ResizeOperation.none;
916
+ },
917
+
918
+ handleWindowResizeMouseEvent: function(event, location){
919
+ var frame;
920
+ // FIXME: assuming no scale or rotation in window.transform
921
+ if (event.type === UIEvent.Type.leftMouseDown){
922
+ frame = event.window._resizeView !== null ? event.window._resizeView.bounds : event.window.bounds;
923
+ this._windowResizeMouseEventData.frame0 = event.window.untransformedFrame;
924
+ this._windowResizeMouseEventData.maximumResize = JSSize(
925
+ event.window.maximumSize.width - frame.size.width,
926
+ event.window.maximumSize.height - frame.size.height
927
+ );
928
+ this._windowResizeMouseEventData.minimumResize = JSSize(
929
+ event.window.minimumSize.width - frame.size.width,
930
+ event.window.minimumSize.height - frame.size.height
931
+ );
932
+ }else if (event.type === UIEvent.Type.leftMouseDragged){
933
+ var diff = location.subtracting(this._windowResizeMouseEventData.location0);
934
+ var over;
935
+ var resizeOperation = this._windowResizeMouseEventData.operation;
936
+ frame = JSRect(this._windowResizeMouseEventData.frame0);
937
+ if (resizeOperation === UIWindowServer.ResizeOperation.top || resizeOperation === UIWindowServer.ResizeOperation.topLeft || resizeOperation === UIWindowServer.ResizeOperation.topRight){
938
+ if (diff.y < 0 && diff.y < -this._windowResizeMouseEventData.maximumResize.height){
939
+ diff.y = -this._windowResizeMouseEventData.maximumResize.height;
940
+ }else if (diff.y > 0 && diff.y > -this._windowResizeMouseEventData.minimumResize.height){
941
+ diff.y = -this._windowResizeMouseEventData.minimumResize.height;
942
+ }
943
+ frame.origin.y += diff.y;
944
+ frame.size.height -= diff.y;
945
+ }else if (resizeOperation === UIWindowServer.ResizeOperation.bottom || resizeOperation === UIWindowServer.ResizeOperation.bottomLeft || resizeOperation === UIWindowServer.ResizeOperation.bottomRight){
946
+ if (diff.y > 0 && diff.y > this._windowResizeMouseEventData.maximumResize.height){
947
+ diff.y = this._windowResizeMouseEventData.maximumResize.height;
948
+ }else if (diff.y < 0 && diff.y < this._windowResizeMouseEventData.minimumResize.height){
949
+ diff.y = this._windowResizeMouseEventData.minimumResize.height;
950
+ }
951
+ frame.size.height += diff.y;
952
+ }
953
+ if (resizeOperation === UIWindowServer.ResizeOperation.left || resizeOperation === UIWindowServer.ResizeOperation.topLeft || resizeOperation === UIWindowServer.ResizeOperation.bottomLeft){
954
+ if (diff.x < 0 && diff.x < -this._windowResizeMouseEventData.maximumResize.width){
955
+ diff.x = -this._windowResizeMouseEventData.maximumResize.width;
956
+ }else if (diff.x > 0 && diff.x > -this._windowResizeMouseEventData.minimumResize.width){
957
+ diff.x = -this._windowResizeMouseEventData.minimumResize.width;
958
+ }
959
+ frame.origin.x += diff.x;
960
+ frame.size.width -= diff.x;
961
+ }else if (resizeOperation === UIWindowServer.ResizeOperation.right || resizeOperation === UIWindowServer.ResizeOperation.topRight || resizeOperation === UIWindowServer.ResizeOperation.bottomRight){
962
+ if (diff.x > 0 && diff.x > this._windowResizeMouseEventData.maximumResize.width){
963
+ diff.x = this._windowResizeMouseEventData.maximumResize.width;
964
+ }else if (diff.x < 0 && diff.x < this._windowResizeMouseEventData.minimumResize.width){
965
+ diff.x = this._windowResizeMouseEventData.minimumResize.width;
966
+ }
967
+ frame.size.width += diff.x;
968
+ }
969
+ event.window.untransformedFrame = frame;
970
+ event.window._windowServerDidResize();
971
+ }
972
+ },
973
+
974
+ cursorForWindowResizeOperation: function(window, resizeOperation){
975
+ // TODO: consider window transform
976
+ if (resizeOperation === UIWindowServer.ResizeOperation.top){
977
+ return UICursor.resizeNorthSouth;
978
+ }
979
+ if (resizeOperation === UIWindowServer.ResizeOperation.left){
980
+ return UICursor.resizeEastWest;
981
+ }
982
+ if (resizeOperation === UIWindowServer.ResizeOperation.bottom){
983
+ return UICursor.resizeNorthSouth;
984
+ }
985
+ if (resizeOperation === UIWindowServer.ResizeOperation.right){
986
+ return UICursor.resizeEastWest;
987
+ }
988
+ if (resizeOperation === UIWindowServer.ResizeOperation.topLeft){
989
+ return UICursor.resizeNorthWestSouthEast;
990
+ }
991
+ if (resizeOperation === UIWindowServer.ResizeOperation.topRight){
992
+ return UICursor.resizeNorthEastSouthWest;
993
+ }
994
+ if (resizeOperation === UIWindowServer.ResizeOperation.bottomLeft){
995
+ return UICursor.resizeNorthEastSouthWest;
996
+ }
997
+ if (resizeOperation === UIWindowServer.ResizeOperation.bottomRight){
998
+ return UICursor.resizeNorthWestSouthEast;
999
+ }
1000
+ return null;
774
1001
  },
775
1002
 
776
1003
  // -----------------------------------------------------------------------
@@ -1129,6 +1356,18 @@ JSClass("UIWindowServer", JSObject, {
1129
1356
 
1130
1357
  });
1131
1358
 
1359
+ UIWindowServer.ResizeOperation = {
1360
+ none: 0,
1361
+ top: 1,
1362
+ left: 2,
1363
+ bottom: 3,
1364
+ right: 4,
1365
+ topLeft: 5,
1366
+ topRight: 6,
1367
+ bottomLeft: 7,
1368
+ bottomRight: 8
1369
+ };
1370
+
1132
1371
  JSClass("UIWindowServerAccessibilityHighlightView", UIView, {
1133
1372
 
1134
1373
  framesetter: JSLazyInitProperty(function(){
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2025.24.0
3
+ JSBundleVersion: 2025.27.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": "2025.24.0",
12
+ "version": "2025.27.0",
13
13
  "license": "SEE LICENSE IN LICENSE.txt",
14
14
  "files": [
15
15
  "*"