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 +1 -1
- package/src/window_selector.mm +54 -14
package/package.json
CHANGED
package/src/window_selector.mm
CHANGED
|
@@ -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:
|
|
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 =
|
|
120
|
+
lineWidth = 1.0;
|
|
114
121
|
} else {
|
|
115
|
-
// Normal state:
|
|
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
|
-
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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"];
|