node-mac-recorder 2.6.7 → 2.6.10

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.
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+
3
+ const WindowSelector = require('./window-selector');
4
+ const MacRecorder = require('./index');
5
+
6
+ async function debugScreenSelection() {
7
+ console.log('šŸ” Screen Selection Debug Test');
8
+ console.log('================================\n');
9
+
10
+ const selector = new WindowSelector();
11
+ const recorder = new MacRecorder();
12
+
13
+ try {
14
+ // First, let's see what displays MacRecorder sees
15
+ console.log('šŸ“ŗ MacRecorder displays:');
16
+ const macDisplays = await recorder.getDisplays();
17
+ macDisplays.forEach((display, i) => {
18
+ console.log(` ${i}: ID=${display.id}, Name="${display.name}", Resolution=${display.resolution}, Primary=${display.isPrimary}`);
19
+ });
20
+ console.log('');
21
+
22
+ // Start screen selection
23
+ console.log('šŸ–„ļø Starting screen selection...');
24
+ console.log(' Move mouse to different screens and click "Start Record" on one of them');
25
+ console.log('');
26
+
27
+ const selectedScreen = await selector.selectScreen();
28
+
29
+ console.log('āœ… Screen selected!');
30
+ console.log('šŸ“Š Selected screen data:');
31
+ console.log(JSON.stringify(selectedScreen, null, 2));
32
+
33
+ // Check if this ID exists in MacRecorder displays
34
+ const matchingDisplay = macDisplays.find(d => d.id === selectedScreen.id);
35
+
36
+ if (matchingDisplay) {
37
+ console.log('\nāœ… MATCH FOUND in MacRecorder displays:');
38
+ console.log(` Selected: ${selectedScreen.name} (ID: ${selectedScreen.id})`);
39
+ console.log(` MacRecorder: ${matchingDisplay.name} (ID: ${matchingDisplay.id})`);
40
+ } else {
41
+ console.log('\nāŒ NO MATCH found in MacRecorder displays!');
42
+ console.log(` Selected ID: ${selectedScreen.id}`);
43
+ console.log(` Available IDs: ${macDisplays.map(d => d.id).join(', ')}`);
44
+ }
45
+
46
+ console.log('\nšŸŽ¬ Testing actual recording...');
47
+ console.log(' Setting displayId option and starting short recording');
48
+
49
+ // Set the display ID from screen selection
50
+ recorder.setOptions({
51
+ displayId: selectedScreen.id,
52
+ includeSystemAudio: false,
53
+ includeMicrophone: false
54
+ });
55
+
56
+ const testFile = `./test-output/screen-selection-test-${Date.now()}.mov`;
57
+ console.log(` Recording file: ${testFile}`);
58
+
59
+ await recorder.startRecording(testFile);
60
+ console.log(' Recording started...');
61
+
62
+ // Record for 3 seconds
63
+ await new Promise(resolve => setTimeout(resolve, 3000));
64
+
65
+ await recorder.stopRecording();
66
+ console.log(' Recording stopped');
67
+
68
+ console.log('\nāœ… Test completed! Check the recording to see if it captured the correct screen.');
69
+
70
+ } catch (error) {
71
+ console.error('\nāŒ Error during test:', error.message);
72
+ if (error.stack) {
73
+ console.error('Stack:', error.stack);
74
+ }
75
+ process.exit(1);
76
+ }
77
+ }
78
+
79
+ if (require.main === module) {
80
+ debugScreenSelection();
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.6.7",
3
+ "version": "2.6.10",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -42,7 +42,8 @@
42
42
  "example:window-selector": "node examples/window-selector-example.js"
43
43
  },
44
44
  "dependencies": {
45
- "node-addon-api": "^7.0.0"
45
+ "node-addon-api": "^7.0.0",
46
+ "node-mac-recorder": "^2.6.7"
46
47
  },
47
48
  "devDependencies": {
48
49
  "node-gyp": "^10.0.0"
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+
3
+ const WindowSelector = require('./window-selector');
4
+
5
+ console.log('Starting screen selection...');
6
+ console.log('Click "Start Record" on ANY screen then this will show the result:');
7
+
8
+ const selector = new WindowSelector();
9
+
10
+ selector.startScreenSelection().then(() => {
11
+ console.log('Screen selection UI shown');
12
+
13
+ // Check every 500ms for selection
14
+ const checkInterval = setInterval(() => {
15
+ const selected = selector.getSelectedScreen();
16
+ if (selected) {
17
+ console.log('\nšŸŽ‰ SCREEN SELECTED!');
18
+ console.log('Selected data:', JSON.stringify(selected, null, 2));
19
+ clearInterval(checkInterval);
20
+ process.exit(0);
21
+ }
22
+ }, 500);
23
+
24
+ // Timeout after 15 seconds
25
+ setTimeout(() => {
26
+ console.log('\nā° Timeout - no screen selected');
27
+ clearInterval(checkInterval);
28
+ process.exit(1);
29
+ }, 15000);
30
+
31
+ }).catch(error => {
32
+ console.error('Error:', error.message);
33
+ process.exit(1);
34
+ });
@@ -61,32 +61,44 @@ void updateScreenOverlays();
61
61
  - (instancetype)initWithFrame:(NSRect)frameRect {
62
62
  self = [super initWithFrame:frameRect];
63
63
  if (self) {
64
+ // Use layer for background instead of custom drawing
64
65
  self.wantsLayer = YES;
65
- self.layer.backgroundColor = [[NSColor clearColor] CGColor];
66
- // Ensure no borders or decorations
67
- self.layer.borderWidth = 0.0;
68
- self.layer.cornerRadius = 0.0;
69
66
  self.isActiveWindow = YES; // Default to active for current window under mouse
67
+
68
+ // Set purple background with border using layer
69
+ [self updateAppearance];
70
+
71
+ // Window selector overlay view created
70
72
  }
71
73
  return self;
72
74
  }
73
75
 
74
- - (void)drawRect:(NSRect)dirtyRect {
75
- [super drawRect:dirtyRect];
76
-
77
- if (!self.windowInfo) return;
78
-
79
- // Background with transparency - same style as screen overlay
76
+ - (void)updateAppearance {
80
77
  if (self.isActiveWindow) {
81
- // Active window: brighter, more opaque (same as active screen)
82
- [[NSColor colorWithRed:0.6 green:0.4 blue:0.9 alpha:0.4] setFill];
78
+ // Active window: brighter background
79
+ self.layer.backgroundColor = [[NSColor colorWithRed:0.6 green:0.4 blue:0.9 alpha:0.4] CGColor];
80
+ // Active window appearance set
83
81
  } else {
84
- // Inactive window: dimmer, less opaque (same as inactive screen)
85
- [[NSColor colorWithRed:0.4 green:0.2 blue:0.6 alpha:0.25] setFill];
82
+ // Inactive window: dimmer background
83
+ self.layer.backgroundColor = [[NSColor colorWithRed:0.4 green:0.2 blue:0.6 alpha:0.25] CGColor];
84
+ // Inactive window appearance set
86
85
  }
87
- NSRectFill(self.bounds);
86
+
87
+ // No border to match screen selector
88
+ self.layer.borderColor = [[NSColor clearColor] CGColor];
89
+ self.layer.borderWidth = 0.0;
90
+ self.layer.cornerRadius = 0.0;
88
91
  }
89
92
 
93
+ - (void)setIsActiveWindow:(BOOL)isActiveWindow {
94
+ if (_isActiveWindow != isActiveWindow) {
95
+ _isActiveWindow = isActiveWindow;
96
+ [self updateAppearance];
97
+ }
98
+ }
99
+
100
+ // Layer-based approach, no custom drawing needed
101
+
90
102
  @end
91
103
 
92
104
  // Recording preview overlay view - full screen with cutout
@@ -210,9 +222,9 @@ void updateScreenOverlays();
210
222
  NSDictionary *screenInfo = [g_allScreens objectAtIndex:screenIndex];
211
223
  g_selectedScreenInfo = [screenInfo retain];
212
224
 
213
- NSLog(@"šŸ–„ļø SCREEN BUTTON CLICKED: %@ (%@)",
225
+ NSLog(@"šŸ–„ļø SCREEN SELECTED: %@ (ID: %@)",
214
226
  [screenInfo objectForKey:@"name"],
215
- [screenInfo objectForKey:@"resolution"]);
227
+ [screenInfo objectForKey:@"id"]);
216
228
 
217
229
  cleanupScreenSelector();
218
230
  }
@@ -506,7 +518,6 @@ void updateOverlay() {
506
518
 
507
519
  // Update overlay view window info
508
520
  [(WindowSelectorOverlayView *)g_overlayView setWindowInfo:windowUnderCursor];
509
- [g_overlayView setNeedsDisplay:YES];
510
521
 
511
522
  // Add/update info label above button
512
523
  NSTextField *infoLabel = nil;
@@ -928,20 +939,57 @@ bool startScreenSelection() {
928
939
  NSMutableArray *screenInfoArray = [[NSMutableArray alloc] init];
929
940
  g_screenOverlayWindows = [[NSMutableArray alloc] init];
930
941
 
942
+ // Get real display IDs like MacRecorder does
943
+ CGDirectDisplayID activeDisplays[32];
944
+ uint32_t displayCount;
945
+ CGError err = CGGetActiveDisplayList(32, activeDisplays, &displayCount);
946
+
947
+ if (err != kCGErrorSuccess) {
948
+ NSLog(@"āŒ Failed to get active display list: %d", err);
949
+ return false;
950
+ }
951
+
931
952
  for (NSInteger i = 0; i < [screens count]; i++) {
932
953
  NSScreen *screen = [screens objectAtIndex:i];
933
954
  NSRect screenFrame = [screen frame];
934
955
 
935
- // Create screen info dictionary
956
+ // Get the real CGDirectDisplayID for this screen by matching frame
957
+ CGDirectDisplayID displayID = 0;
958
+
959
+ // Find matching display by comparing bounds
960
+ for (uint32_t j = 0; j < displayCount; j++) {
961
+ CGDirectDisplayID candidateID = activeDisplays[j];
962
+ CGRect displayBounds = CGDisplayBounds(candidateID);
963
+
964
+ // Compare screen frame with display bounds
965
+ if (fabs(screenFrame.origin.x - displayBounds.origin.x) < 1.0 &&
966
+ fabs(screenFrame.origin.y - displayBounds.origin.y) < 1.0 &&
967
+ fabs(screenFrame.size.width - displayBounds.size.width) < 1.0 &&
968
+ fabs(screenFrame.size.height - displayBounds.size.height) < 1.0) {
969
+ displayID = candidateID;
970
+ // Screen matched to display ID
971
+ break;
972
+ }
973
+ }
974
+
975
+ // Fallback: use array index if no match found
976
+ if (displayID == 0 && i < displayCount) {
977
+ displayID = activeDisplays[i];
978
+ // Used fallback display ID
979
+ } else if (displayID == 0) {
980
+ NSLog(@"āŒ Screen %ld could not get Display ID", (long)i);
981
+ }
982
+
983
+ // Create screen info dictionary with real display ID
936
984
  NSMutableDictionary *screenInfo = [[NSMutableDictionary alloc] init];
937
- [screenInfo setObject:[NSNumber numberWithInteger:i] forKey:@"id"];
985
+ [screenInfo setObject:[NSNumber numberWithUnsignedInt:displayID] forKey:@"id"]; // Real display ID
938
986
  [screenInfo setObject:[NSString stringWithFormat:@"Display %ld", (long)(i + 1)] forKey:@"name"];
939
987
  [screenInfo setObject:[NSNumber numberWithInt:(int)screenFrame.origin.x] forKey:@"x"];
940
988
  [screenInfo setObject:[NSNumber numberWithInt:(int)screenFrame.origin.y] forKey:@"y"];
941
989
  [screenInfo setObject:[NSNumber numberWithInt:(int)screenFrame.size.width] forKey:@"width"];
942
990
  [screenInfo setObject:[NSNumber numberWithInt:(int)screenFrame.size.height] forKey:@"height"];
943
991
  [screenInfo setObject:[NSString stringWithFormat:@"%.0fx%.0f", screenFrame.size.width, screenFrame.size.height] forKey:@"resolution"];
944
- [screenInfo setObject:[NSNumber numberWithBool:(i == 0)] forKey:@"isPrimary"]; // First screen is primary
992
+ [screenInfo setObject:[NSNumber numberWithBool:(displayID == CGMainDisplayID())] forKey:@"isPrimary"]; // Real primary check
945
993
  [screenInfoArray addObject:screenInfo];
946
994
 
947
995
  // Create overlay window for this screen (FULL screen including menu bar)
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ const WindowSelector = require('./window-selector');
4
+
5
+ async function testRealScreenIDs() {
6
+ console.log('Testing real screen ID generation...\n');
7
+
8
+ const selector = new WindowSelector();
9
+
10
+ // Start screen selection to generate screen info
11
+ console.log('Starting screen selection (will timeout in 3 seconds)...');
12
+
13
+ const startPromise = selector.startScreenSelection();
14
+
15
+ // Wait a bit for screen info to be generated
16
+ await new Promise(resolve => setTimeout(resolve, 1000));
17
+
18
+ // Try to get selected screen info (should be null since nothing selected)
19
+ const selectedInfo = selector.getSelectedScreen();
20
+ console.log('Selected screen info (should be null):', selectedInfo);
21
+
22
+ // Clean up
23
+ try {
24
+ await selector.stopScreenSelection();
25
+ } catch (e) {
26
+ // Ignore
27
+ }
28
+
29
+ console.log('\nTest completed. Check logs above for screen creation details.');
30
+ }
31
+
32
+ testRealScreenIDs().catch(console.error);