node-mac-recorder 2.10.17 → 2.10.19
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/quick-test.js +28 -43
- package/src/window_selector.mm +81 -9
package/package.json
CHANGED
package/quick-test.js
CHANGED
|
@@ -1,50 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const WindowSelector = require('./window-selector');
|
|
2
4
|
|
|
3
5
|
async function quickTest() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
console.log('🧪 Quick Window Selector Test');
|
|
7
|
+
console.log('============================\n');
|
|
8
|
+
|
|
9
|
+
const selector = new WindowSelector();
|
|
10
|
+
|
|
8
11
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console.log('
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
console.log('🎵 Sistem sesi yakalama çalışmalı');
|
|
24
|
-
} else {
|
|
25
|
-
console.log('\n⚠️ Sistem sesi cihazı yok');
|
|
26
|
-
console.log('💡 BlackHole veya Soundflower yüklemen gerekiyor');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Kısa test kayıt
|
|
30
|
-
console.log('\n🔴 2 saniyelik test kayıt başlıyor...');
|
|
31
|
-
console.log('🎵 Şimdi müzik çal!');
|
|
32
|
-
|
|
33
|
-
await recorder.startRecording('./test-output/quick-test.mov', {
|
|
34
|
-
includeSystemAudio: true,
|
|
35
|
-
includeMicrophone: false,
|
|
36
|
-
systemAudioDeviceId: sysDevice?.id,
|
|
37
|
-
captureArea: { x: 0, y: 0, width: 200, height: 150 }
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
41
|
-
await recorder.stopRecording();
|
|
42
|
-
|
|
43
|
-
console.log('✅ Test tamamlandı! ./test-output/quick-test.mov dosyasını kontrol et');
|
|
44
|
-
|
|
12
|
+
console.log('✅ Starting window selection...');
|
|
13
|
+
console.log('🎯 Hover over windows to see highlighting (no border)');
|
|
14
|
+
console.log('🔒 Window dragging should be blocked');
|
|
15
|
+
console.log('⌛ Test will auto-stop in 15 seconds\n');
|
|
16
|
+
|
|
17
|
+
await selector.startSelection();
|
|
18
|
+
|
|
19
|
+
// Auto stop after 15 seconds
|
|
20
|
+
setTimeout(async () => {
|
|
21
|
+
console.log('\n⏹️ Auto-stopping test...');
|
|
22
|
+
await selector.cleanup();
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}, 15000);
|
|
25
|
+
|
|
45
26
|
} catch (error) {
|
|
46
|
-
console.error('❌
|
|
27
|
+
console.error('❌ Test failed:', error.message);
|
|
28
|
+
await selector.cleanup();
|
|
29
|
+
process.exit(1);
|
|
47
30
|
}
|
|
48
31
|
}
|
|
49
32
|
|
|
50
|
-
|
|
33
|
+
if (require.main === module) {
|
|
34
|
+
quickTest().catch(console.error);
|
|
35
|
+
}
|
package/src/window_selector.mm
CHANGED
|
@@ -60,6 +60,12 @@ void updateScreenOverlays();
|
|
|
60
60
|
- (void)setHighlightFrame:(NSRect)frame;
|
|
61
61
|
@end
|
|
62
62
|
|
|
63
|
+
// Custom button with hover effects
|
|
64
|
+
@interface HoverButton : NSButton
|
|
65
|
+
@property (nonatomic) BOOL isHovered;
|
|
66
|
+
- (void)setupHoverTracking;
|
|
67
|
+
@end
|
|
68
|
+
|
|
63
69
|
@implementation WindowSelectorOverlayView
|
|
64
70
|
|
|
65
71
|
- (instancetype)initWithFrame:(NSRect)frameRect {
|
|
@@ -95,16 +101,18 @@ void updateScreenOverlays();
|
|
|
95
101
|
xRadius:8.0
|
|
96
102
|
yRadius:8.0];
|
|
97
103
|
|
|
98
|
-
// Fill color based on toggle state
|
|
104
|
+
// Fill color and border based on toggle state
|
|
99
105
|
NSColor *fillColor;
|
|
100
106
|
NSColor *strokeColor;
|
|
101
107
|
CGFloat lineWidth;
|
|
102
108
|
|
|
103
109
|
if (self.isToggled) {
|
|
110
|
+
// Locked state: thicker border
|
|
104
111
|
fillColor = [NSColor colorWithRed:0.6 green:0.4 blue:0.9 alpha:0.4];
|
|
105
112
|
strokeColor = [NSColor colorWithRed:0.45 green:0.25 blue:0.75 alpha:0.9];
|
|
106
113
|
lineWidth = 3.0;
|
|
107
114
|
} else {
|
|
115
|
+
// Normal state: thin border
|
|
108
116
|
fillColor = [NSColor colorWithRed:0.6 green:0.4 blue:0.9 alpha:0.4];
|
|
109
117
|
strokeColor = [NSColor whiteColor];
|
|
110
118
|
lineWidth = 1.0;
|
|
@@ -172,6 +180,62 @@ void updateScreenOverlays();
|
|
|
172
180
|
|
|
173
181
|
@end
|
|
174
182
|
|
|
183
|
+
@implementation HoverButton
|
|
184
|
+
|
|
185
|
+
- (instancetype)initWithFrame:(NSRect)frameRect {
|
|
186
|
+
self = [super initWithFrame:frameRect];
|
|
187
|
+
if (self) {
|
|
188
|
+
self.isHovered = NO;
|
|
189
|
+
[self setupHoverTracking];
|
|
190
|
+
}
|
|
191
|
+
return self;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
- (void)setupHoverTracking {
|
|
195
|
+
NSTrackingArea *trackingArea = [[NSTrackingArea alloc]
|
|
196
|
+
initWithRect:self.bounds
|
|
197
|
+
options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
|
|
198
|
+
owner:self
|
|
199
|
+
userInfo:nil];
|
|
200
|
+
[self addTrackingArea:trackingArea];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
- (void)mouseEntered:(NSEvent *)event {
|
|
204
|
+
self.isHovered = YES;
|
|
205
|
+
[self animateScale:1.2 duration:0.15];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
- (void)mouseExited:(NSEvent *)event {
|
|
209
|
+
self.isHovered = NO;
|
|
210
|
+
[self animateScale:1.0 duration:0.15];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
- (void)animateScale:(CGFloat)scale duration:(NSTimeInterval)duration {
|
|
214
|
+
[NSAnimationContext beginGrouping];
|
|
215
|
+
[NSAnimationContext currentContext].duration = duration;
|
|
216
|
+
[NSAnimationContext currentContext].timingFunction =
|
|
217
|
+
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
|
218
|
+
|
|
219
|
+
CATransform3D transform = CATransform3DMakeScale(scale, scale, 1.0);
|
|
220
|
+
self.layer.transform = transform;
|
|
221
|
+
|
|
222
|
+
[NSAnimationContext endGrouping];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
- (void)updateTrackingAreas {
|
|
226
|
+
[super updateTrackingAreas];
|
|
227
|
+
|
|
228
|
+
// Remove old tracking areas
|
|
229
|
+
for (NSTrackingArea *area in self.trackingAreas) {
|
|
230
|
+
[self removeTrackingArea:area];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Add new tracking area
|
|
234
|
+
[self setupHoverTracking];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@end
|
|
238
|
+
|
|
175
239
|
// Recording preview overlay view - full screen with cutout
|
|
176
240
|
@interface RecordingPreviewView : NSView
|
|
177
241
|
@property (nonatomic, strong) NSDictionary *recordingWindowInfo;
|
|
@@ -1249,8 +1313,8 @@ bool startScreenSelection() {
|
|
|
1249
1313
|
|
|
1250
1314
|
// Note: NSWindow doesn't have setWantsLayer method, only NSView does
|
|
1251
1315
|
|
|
1252
|
-
// Create select button with more padding
|
|
1253
|
-
NSButton *selectButton = [[
|
|
1316
|
+
// Create select button with more padding and hover effects
|
|
1317
|
+
NSButton *selectButton = [[HoverButton alloc] initWithFrame:NSMakeRect(0, 0, 200, 60)];
|
|
1254
1318
|
[selectButton setTitle:@"Start Record"];
|
|
1255
1319
|
[selectButton setButtonType:NSButtonTypeMomentaryPushIn];
|
|
1256
1320
|
[selectButton setBordered:NO];
|
|
@@ -1292,8 +1356,8 @@ bool startScreenSelection() {
|
|
|
1292
1356
|
[selectButton setFocusRingType:NSFocusRingTypeNone];
|
|
1293
1357
|
[selectButton setShowsBorderOnlyWhileMouseInside:NO];
|
|
1294
1358
|
|
|
1295
|
-
// Create cancel button for screen selection
|
|
1296
|
-
NSButton *screenCancelButton = [[
|
|
1359
|
+
// Create cancel button for screen selection with hover effects
|
|
1360
|
+
NSButton *screenCancelButton = [[HoverButton alloc] initWithFrame:NSMakeRect(0, 0, 120, 40)];
|
|
1297
1361
|
[screenCancelButton setTitle:@"Cancel"];
|
|
1298
1362
|
[screenCancelButton setButtonType:NSButtonTypeMomentaryPushIn];
|
|
1299
1363
|
[screenCancelButton setBordered:NO];
|
|
@@ -1586,6 +1650,14 @@ Napi::Value StartWindowSelection(const Napi::CallbackInfo& info) {
|
|
|
1586
1650
|
}
|
|
1587
1651
|
|
|
1588
1652
|
@try {
|
|
1653
|
+
// Clean up any existing overlay first
|
|
1654
|
+
if (g_overlayWindow) {
|
|
1655
|
+
[g_overlayWindow close];
|
|
1656
|
+
g_overlayWindow = nil;
|
|
1657
|
+
g_overlayView = nil;
|
|
1658
|
+
g_selectButton = nil;
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1589
1661
|
// Get all windows
|
|
1590
1662
|
g_allWindows = [getAllSelectableWindows() retain];
|
|
1591
1663
|
|
|
@@ -1642,8 +1714,8 @@ Napi::Value StartWindowSelection(const Napi::CallbackInfo& info) {
|
|
|
1642
1714
|
[g_overlayWindow setMovable:NO];
|
|
1643
1715
|
[g_overlayWindow setMovableByWindowBackground:NO];
|
|
1644
1716
|
|
|
1645
|
-
// Create select button with purple theme
|
|
1646
|
-
g_selectButton = [[
|
|
1717
|
+
// Create select button with purple theme and hover effects
|
|
1718
|
+
g_selectButton = [[HoverButton alloc] initWithFrame:NSMakeRect(0, 0, 200, 60)];
|
|
1647
1719
|
[g_selectButton setTitle:@"Start Record"];
|
|
1648
1720
|
[g_selectButton setButtonType:NSButtonTypeMomentaryPushIn];
|
|
1649
1721
|
[g_selectButton setBordered:NO];
|
|
@@ -1683,8 +1755,8 @@ Napi::Value StartWindowSelection(const Napi::CallbackInfo& info) {
|
|
|
1683
1755
|
// Add select button directly to window (not view) for proper layering
|
|
1684
1756
|
[g_overlayWindow.contentView addSubview:g_selectButton];
|
|
1685
1757
|
|
|
1686
|
-
// Create cancel button
|
|
1687
|
-
NSButton *cancelButton = [[
|
|
1758
|
+
// Create cancel button with hover effects
|
|
1759
|
+
NSButton *cancelButton = [[HoverButton alloc] initWithFrame:NSMakeRect(0, 0, 120, 40)];
|
|
1688
1760
|
[cancelButton setTitle:@"Cancel"];
|
|
1689
1761
|
[cancelButton setButtonType:NSButtonTypeMomentaryPushIn];
|
|
1690
1762
|
[cancelButton setBordered:NO];
|