node-mac-recorder 2.10.20 → 2.10.22

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.10.20",
3
+ "version": "2.10.22",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -66,6 +66,10 @@ void updateScreenOverlays();
66
66
  - (void)setupHoverTracking;
67
67
  @end
68
68
 
69
+ // Window delegate to prevent focus
70
+ @interface OverlayWindowDelegate : NSObject <NSWindowDelegate>
71
+ @end
72
+
69
73
  @implementation WindowSelectorOverlayView
70
74
 
71
75
  - (instancetype)initWithFrame:(NSRect)frameRect {
@@ -79,6 +83,9 @@ void updateScreenOverlays();
79
83
  // Transparent background for full-screen overlay
80
84
  self.layer.backgroundColor = [[NSColor clearColor] CGColor];
81
85
 
86
+ // Disable focus ring completely
87
+ [self setFocusRingType:NSFocusRingTypeNone];
88
+
82
89
  // Window selector overlay view created
83
90
  }
84
91
  return self;
@@ -107,12 +114,12 @@ void updateScreenOverlays();
107
114
  CGFloat lineWidth;
108
115
 
109
116
  if (self.isToggled) {
110
- // Locked state: thicker border
117
+ // Locked state: same 1px border but different color
111
118
  fillColor = [NSColor colorWithRed:0.6 green:0.4 blue:0.9 alpha:0.4];
112
119
  strokeColor = [NSColor colorWithRed:0.45 green:0.25 blue:0.75 alpha:0.9];
113
- lineWidth = 3.0;
120
+ lineWidth = 1.0;
114
121
  } else {
115
- // Normal state: thin border
122
+ // Normal state: 1px border
116
123
  fillColor = [NSColor colorWithRed:0.6 green:0.4 blue:0.9 alpha:0.4];
117
124
  strokeColor = [NSColor whiteColor];
118
125
  lineWidth = 1.0;
@@ -131,6 +138,14 @@ void updateScreenOverlays();
131
138
  [self setNeedsDisplay:YES];
132
139
  }
133
140
 
141
+ - (BOOL)acceptsFirstResponder {
142
+ return NO; // Never accept focus to prevent blue ring
143
+ }
144
+
145
+ - (BOOL)canBecomeKeyView {
146
+ return NO; // Never become key view
147
+ }
148
+
134
149
  - (void)setIsActiveWindow:(BOOL)isActiveWindow {
135
150
  if (_isActiveWindow != isActiveWindow) {
136
151
  _isActiveWindow = isActiveWindow;
@@ -239,6 +254,18 @@ void updateScreenOverlays();
239
254
 
240
255
  @end
241
256
 
257
+ @implementation OverlayWindowDelegate
258
+
259
+ - (BOOL)windowShouldBecomeKey:(NSWindow *)window {
260
+ return NO; // Prevent window from becoming key to avoid focus ring
261
+ }
262
+
263
+ - (BOOL)windowShouldBecomeMain:(NSWindow *)window {
264
+ return NO; // Prevent window from becoming main
265
+ }
266
+
267
+ @end
268
+
242
269
  // Recording preview overlay view - full screen with cutout
243
270
  @interface RecordingPreviewView : NSView
244
271
  @property (nonatomic, strong) NSDictionary *recordingWindowInfo;
@@ -906,7 +933,8 @@ void updateOverlay() {
906
933
  }
907
934
 
908
935
  [g_overlayWindow orderFront:nil];
909
- [g_overlayWindow makeKeyAndOrderFront:nil];
936
+ // DON'T make key - prevents focus ring
937
+ // [g_overlayWindow makeKeyAndOrderFront:nil];
910
938
 
911
939
  // Ensure subviews (except overlay view itself) have no borders after positioning
912
940
  for (NSView *subview in [g_overlayWindow.contentView subviews]) {
@@ -1027,7 +1055,7 @@ bool showRecordingPreview(NSDictionary *windowInfo) {
1027
1055
  [g_recordingPreviewWindow setAcceptsMouseMovedEvents:NO];
1028
1056
  [g_recordingPreviewWindow setHasShadow:NO];
1029
1057
  [g_recordingPreviewWindow setAlphaValue:1.0];
1030
- [g_recordingPreviewWindow setCollectionBehavior:NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorIgnoresCycle];
1058
+ [g_recordingPreviewWindow setCollectionBehavior:NSWindowCollectionBehaviorTransient | NSWindowCollectionBehaviorIgnoresCycle];
1031
1059
 
1032
1060
  // Remove any default window decorations and borders
1033
1061
  [g_recordingPreviewWindow setTitlebarAppearsTransparent:YES];
@@ -1156,7 +1184,7 @@ void updateScreenOverlays() {
1156
1184
  // Ensure ALL overlays are visible, but active one is on top
1157
1185
  [overlayWindow orderFront:nil];
1158
1186
  if (isActiveScreen) {
1159
- [overlayWindow makeKeyAndOrderFront:nil];
1187
+ [overlayWindow orderFront:nil]; // Don't make key
1160
1188
  } else {
1161
1189
  [overlayWindow orderFront:nil]; // Keep inactive screens visible too
1162
1190
  }
@@ -1301,7 +1329,7 @@ bool startScreenSelection() {
1301
1329
  [overlayWindow setHasShadow:NO];
1302
1330
  [overlayWindow setAlphaValue:1.0];
1303
1331
  // Ensure window appears on all spaces and stays put - match g_overlayWindow
1304
- [overlayWindow setCollectionBehavior:NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorIgnoresCycle];
1332
+ [overlayWindow setCollectionBehavior:NSWindowCollectionBehaviorTransient | NSWindowCollectionBehaviorIgnoresCycle];
1305
1333
 
1306
1334
  // Remove any default window decorations and borders
1307
1335
  [overlayWindow setTitlebarAppearsTransparent:YES];
@@ -1474,12 +1502,12 @@ bool startScreenSelection() {
1474
1502
  // Show overlay - different strategy for secondary screens
1475
1503
  if (i == 0) {
1476
1504
  // Primary screen
1477
- [overlayWindow makeKeyAndOrderFront:nil];
1505
+ [overlayWindow orderFront:nil]; // Don't make key
1478
1506
  // Primary screen overlay shown
1479
1507
  } else {
1480
1508
  // Secondary screens - more aggressive approach
1481
1509
  [overlayWindow orderFront:nil];
1482
- [overlayWindow makeKeyAndOrderFront:nil]; // Try makeKey too
1510
+ [overlayWindow orderFront:nil]; // Don't make key // Try makeKey too
1483
1511
  [overlayWindow setLevel:CGWindowLevelForKey(kCGMaximumWindowLevelKey)]; // Match g_overlayWindow level
1484
1512
 
1485
1513
  // Secondary screen overlay shown
@@ -1487,7 +1515,7 @@ bool startScreenSelection() {
1487
1515
  // Double-check with delayed re-show
1488
1516
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
1489
1517
  [overlayWindow orderFront:nil];
1490
- [overlayWindow makeKeyAndOrderFront:nil];
1518
+ [overlayWindow orderFront:nil]; // Don't make key
1491
1519
  });
1492
1520
  }
1493
1521
 
@@ -1601,7 +1629,7 @@ bool showScreenRecordingPreview(NSDictionary *screenInfo) {
1601
1629
  // no border
1602
1630
  [overlayWindow setStyleMask:NSWindowStyleMaskBorderless];
1603
1631
  [overlayWindow setAlphaValue:1.0];
1604
- [overlayWindow setCollectionBehavior:NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorIgnoresCycle];
1632
+ [overlayWindow setCollectionBehavior:NSWindowCollectionBehaviorTransient | NSWindowCollectionBehaviorIgnoresCycle];
1605
1633
 
1606
1634
 
1607
1635
  // Force content view to have no borders
@@ -1624,7 +1652,7 @@ bool showScreenRecordingPreview(NSDictionary *screenInfo) {
1624
1652
 
1625
1653
 
1626
1654
  [overlayWindow orderFront:nil];
1627
- [overlayWindow makeKeyAndOrderFront:nil];
1655
+ // [overlayWindow makeKeyAndOrderFront:nil];
1628
1656
 
1629
1657
  // Note: NSWindow doesn't have setWantsLayer method, only NSView does
1630
1658
 
@@ -1697,7 +1725,7 @@ Napi::Value StartWindowSelection(const Napi::CallbackInfo& info) {
1697
1725
  [g_overlayWindow setAcceptsMouseMovedEvents:YES];
1698
1726
  [g_overlayWindow setHasShadow:NO];
1699
1727
  [g_overlayWindow setAlphaValue:1.0];
1700
- [g_overlayWindow setCollectionBehavior:NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorFullScreenAuxiliary | NSWindowCollectionBehaviorIgnoresCycle];
1728
+ [g_overlayWindow setCollectionBehavior:NSWindowCollectionBehaviorTransient | NSWindowCollectionBehaviorIgnoresCycle];
1701
1729
 
1702
1730
  // Remove any default window decorations and borders
1703
1731
  [g_overlayWindow setTitlebarAppearsTransparent:YES];
@@ -1716,17 +1744,29 @@ Napi::Value StartWindowSelection(const Napi::CallbackInfo& info) {
1716
1744
 
1717
1745
  // Note: NSWindow doesn't have setWantsLayer method, only NSView does
1718
1746
 
1719
- // Force content view to have no borders
1747
+ // Force content view to have no borders and no focus ring
1720
1748
  g_overlayWindow.contentView.wantsLayer = YES;
1721
1749
  g_overlayWindow.contentView.layer.borderWidth = 0.0;
1722
1750
  g_overlayWindow.contentView.layer.borderColor = [[NSColor clearColor] CGColor];
1723
1751
  g_overlayWindow.contentView.layer.cornerRadius = 0.0;
1724
1752
  g_overlayWindow.contentView.layer.masksToBounds = YES;
1725
1753
 
1754
+ // Disable focus ring on overlay view
1755
+ if ([g_overlayView respondsToSelector:@selector(setFocusRingType:)]) {
1756
+ [(NSView*)g_overlayView setFocusRingType:NSFocusRingTypeNone];
1757
+ }
1758
+
1726
1759
  // Additional window styling to ensure no borders or decorations
1727
1760
  [g_overlayWindow setMovable:NO];
1728
1761
  [g_overlayWindow setMovableByWindowBackground:NO];
1729
1762
 
1763
+ // Set delegate to prevent focus
1764
+ static OverlayWindowDelegate *windowDelegate = nil;
1765
+ if (!windowDelegate) {
1766
+ windowDelegate = [[OverlayWindowDelegate alloc] init];
1767
+ }
1768
+ [g_overlayWindow setDelegate:windowDelegate];
1769
+
1730
1770
  // Create select button with purple theme and hover effects
1731
1771
  g_selectButton = [[HoverButton alloc] initWithFrame:NSMakeRect(0, 0, 200, 60)];
1732
1772
  [g_selectButton setTitle:@"Start Record"];