node-mac-recorder 2.15.9 → 2.15.11

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,69 @@
1
+ const MacRecorder = require('./index');
2
+
3
+ async function debugCoordinates() {
4
+ const recorder = new MacRecorder();
5
+ const displays = await recorder.getDisplays();
6
+
7
+ console.log('šŸ–„ļø Display coordinates analysis:');
8
+ displays.forEach((display, index) => {
9
+ console.log(`Display ${index}: ${display.name}`);
10
+ console.log(` ID: ${display.id}`);
11
+ console.log(` Position: (${display.x}, ${display.y})`);
12
+ console.log(` Size: ${display.width}x${display.height}`);
13
+ console.log(` isPrimary: ${display.isPrimary}`);
14
+ console.log('');
15
+ });
16
+
17
+ // Calculate combined frame like we do in native code
18
+ let combinedFrame = { x: 0, y: 0, width: 0, height: 0 };
19
+ let first = true;
20
+
21
+ for (const display of displays) {
22
+ if (first) {
23
+ combinedFrame = {
24
+ x: display.x,
25
+ y: display.y,
26
+ width: display.width,
27
+ height: display.height
28
+ };
29
+ first = false;
30
+ } else {
31
+ const minX = Math.min(combinedFrame.x, display.x);
32
+ const minY = Math.min(combinedFrame.y, display.y);
33
+ const maxX = Math.max(combinedFrame.x + combinedFrame.width, display.x + display.width);
34
+ const maxY = Math.max(combinedFrame.y + combinedFrame.height, display.y + display.height);
35
+
36
+ combinedFrame = {
37
+ x: minX,
38
+ y: minY,
39
+ width: maxX - minX,
40
+ height: maxY - minY
41
+ };
42
+ }
43
+ }
44
+
45
+ console.log('šŸ“ Combined frame calculation:');
46
+ console.log(` Origin: (${combinedFrame.x}, ${combinedFrame.y})`);
47
+ console.log(` Size: ${combinedFrame.width}x${combinedFrame.height}`);
48
+ console.log('');
49
+
50
+ console.log('šŸ”„ Coordinate conversion examples:');
51
+ displays.forEach((display, index) => {
52
+ console.log(`Display ${index} (${display.name}):`);
53
+ const localOriginX = display.x - combinedFrame.x;
54
+ const localOriginY = display.y - combinedFrame.y;
55
+ console.log(` Global offset from combined: (${localOriginX}, ${localOriginY})`);
56
+
57
+ // Test window at display origin
58
+ const testWindowGlobalX = display.x + 100;
59
+ const testWindowGlobalY = display.y + 100;
60
+ const localWindowX = testWindowGlobalX - combinedFrame.x;
61
+ const localWindowY = testWindowGlobalY - combinedFrame.y;
62
+
63
+ console.log(` Test window at (${testWindowGlobalX}, ${testWindowGlobalY}) global`);
64
+ console.log(` -> Local coordinates: (${localWindowX}, ${localWindowY})`);
65
+ console.log('');
66
+ });
67
+ }
68
+
69
+ debugCoordinates();
@@ -0,0 +1,84 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ async function debugPrimaryDisplay() {
5
+ console.log('šŸ” Debugging primary display window selector...');
6
+
7
+ const recorder = new MacRecorder();
8
+ const displays = await recorder.getDisplays();
9
+
10
+ console.log('šŸ“Š Display analysis:');
11
+ displays.forEach(display => {
12
+ console.log(`${display.name}: (${display.x}, ${display.y}) ${display.width}x${display.height} ${display.isPrimary ? '[PRIMARY]' : '[SECONDARY]'}`);
13
+ });
14
+
15
+ // Calculate combined frame like in native code
16
+ const primary = displays.find(d => d.isPrimary);
17
+ const secondary = displays.find(d => !d.isPrimary);
18
+
19
+ console.log('\n🧮 Coordinate calculations:');
20
+ console.log(`Primary: (${primary.x}, ${primary.y})`);
21
+ console.log(`Secondary: (${secondary.x}, ${secondary.y})`);
22
+
23
+ // Combined frame calculation
24
+ const minX = Math.min(primary.x, secondary.x);
25
+ const minY = Math.min(primary.y, secondary.y);
26
+ const maxX = Math.max(primary.x + primary.width, secondary.x + secondary.width);
27
+ const maxY = Math.max(primary.y + primary.height, secondary.y + secondary.height);
28
+
29
+ const combinedFrame = {
30
+ x: minX,
31
+ y: minY,
32
+ width: maxX - minX,
33
+ height: maxY - minY
34
+ };
35
+
36
+ console.log(`Combined frame: (${combinedFrame.x}, ${combinedFrame.y}) ${combinedFrame.width}x${combinedFrame.height}`);
37
+
38
+ // Test coordinate conversion for a primary display window
39
+ const testPrimaryWindowX = 100; // Window at (100, 100) on primary
40
+ const testPrimaryWindowY = 100;
41
+
42
+ const localX = testPrimaryWindowX - combinedFrame.x;
43
+ const localY = testPrimaryWindowY - combinedFrame.y;
44
+
45
+ console.log(`\nšŸŽÆ Primary window test:`);
46
+ console.log(`Global window: (${testPrimaryWindowX}, ${testPrimaryWindowY})`);
47
+ console.log(`Combined origin: (${combinedFrame.x}, ${combinedFrame.y})`);
48
+ console.log(`Local coordinates: (${localX}, ${localY})`);
49
+ console.log(`Combined height: ${combinedFrame.height}`);
50
+ console.log(`Converted Y: ${combinedFrame.height - localY - 200}`); // Assuming 200px window height
51
+
52
+ // Test for secondary display window
53
+ const testSecondaryWindowX = secondary.x + 100;
54
+ const testSecondaryWindowY = secondary.y + 100;
55
+
56
+ const localSecondaryX = testSecondaryWindowX - combinedFrame.x;
57
+ const localSecondaryY = testSecondaryWindowY - combinedFrame.y;
58
+
59
+ console.log(`\nšŸŽÆ Secondary window test:`);
60
+ console.log(`Global window: (${testSecondaryWindowX}, ${testSecondaryWindowY})`);
61
+ console.log(`Local coordinates: (${localSecondaryX}, ${localSecondaryY})`);
62
+ console.log(`Converted Y: ${combinedFrame.height - localSecondaryY - 200}`);
63
+
64
+ console.log('\n🧪 Starting actual window selection test...');
65
+ console.log(' - Move cursor to primary display windows');
66
+ console.log(' - Check if buttons appear');
67
+ console.log(' - Check console logs for coordinate calculations');
68
+
69
+ const selector = new WindowSelector();
70
+
71
+ try {
72
+ await selector.startSelection();
73
+
74
+ // Let it run for 15 seconds for debugging
75
+ await new Promise(resolve => setTimeout(resolve, 15000));
76
+
77
+ await selector.stopSelection();
78
+
79
+ } catch (error) {
80
+ console.log(`āŒ Test failed: ${error.message}`);
81
+ }
82
+ }
83
+
84
+ debugPrimaryDisplay();
@@ -0,0 +1,74 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ async function finalMultiDisplayTest() {
5
+ console.log('šŸŽ‰ FINAL Multi-Display Test');
6
+ console.log('='.repeat(40));
7
+
8
+ const recorder = new MacRecorder();
9
+ const displays = await recorder.getDisplays();
10
+
11
+ console.log('šŸ“Š Display Configuration:');
12
+ displays.forEach(display => {
13
+ console.log(` ${display.name}: (${display.x}, ${display.y}) ${display.width}x${display.height} ${display.isPrimary ? '[PRIMARY]' : ''}`);
14
+ });
15
+
16
+ console.log('\nāœ… All coordinate fixes applied:');
17
+ console.log(' - Screen selector: Local coordinates for UI elements');
18
+ console.log(' - Window selector: Primary/secondary coordinate handling');
19
+ console.log(' - Display recording: Correct display ID mapping');
20
+
21
+ console.log('\n🧪 Testing window selector...');
22
+ console.log('šŸ“ IMPORTANT: Test windows on BOTH displays');
23
+ console.log(' - Primary display: Should show buttons/UI correctly now');
24
+ console.log(' - Secondary display: Should continue working');
25
+
26
+ const selector = new WindowSelector();
27
+
28
+ try {
29
+ await selector.startSelection();
30
+
31
+ console.log('\nā±ļø Running for 30 seconds - test both displays thoroughly...');
32
+ await new Promise(resolve => setTimeout(resolve, 30000));
33
+
34
+ await selector.stopSelection();
35
+
36
+ console.log('āœ… Window selector test completed!');
37
+
38
+ // Test recording on both displays
39
+ console.log('\nšŸŽ„ Testing recording on both displays...');
40
+
41
+ for (const display of displays) {
42
+ console.log(`\nšŸ“¹ Testing ${display.name} recording...`);
43
+
44
+ try {
45
+ const outputPath = `./test-output/final-test-${display.id}.mov`;
46
+
47
+ await recorder.startRecording(outputPath, {
48
+ displayId: display.id,
49
+ captureCursor: true,
50
+ includeMicrophone: false,
51
+ includeSystemAudio: false
52
+ });
53
+
54
+ console.log(`āœ… Recording started on ${display.name}`);
55
+ await new Promise(resolve => setTimeout(resolve, 2000));
56
+
57
+ await recorder.stopRecording();
58
+ console.log(`āœ… Recording completed on ${display.name}`);
59
+
60
+ } catch (error) {
61
+ console.log(`āŒ Recording failed on ${display.name}: ${error.message}`);
62
+ }
63
+ }
64
+
65
+ console.log('\nšŸŽ‰ ALL MULTI-DISPLAY TESTS COMPLETED!');
66
+ console.log('āœ… Window selector should now work on both displays');
67
+ console.log('āœ… Recording should work on both displays');
68
+
69
+ } catch (error) {
70
+ console.log(`āŒ Test failed: ${error.message}`);
71
+ }
72
+ }
73
+
74
+ finalMultiDisplayTest();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.15.9",
3
+ "version": "2.15.11",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
package/publish.sh ADDED
@@ -0,0 +1,90 @@
1
+ #!/bin/bash
2
+
3
+ # Publish script for node-mac-recorder
4
+ # Usage: ./publish.sh <patch|minor|major> "commit message"
5
+
6
+ # Check if correct number of arguments provided
7
+ if [ $# -ne 2 ]; then
8
+ echo "āŒ Usage: $0 <patch|minor|major> \"commit message\""
9
+ echo " Example: $0 patch \"Fix multi-display coordinate issues\""
10
+ exit 1
11
+ fi
12
+
13
+ VERSION_TYPE=$1
14
+ COMMIT_MESSAGE=$2
15
+
16
+ # Validate version type
17
+ if [[ "$VERSION_TYPE" != "patch" && "$VERSION_TYPE" != "minor" && "$VERSION_TYPE" != "major" ]]; then
18
+ echo "āŒ Invalid version type: $VERSION_TYPE"
19
+ echo " Must be one of: patch, minor, major"
20
+ exit 1
21
+ fi
22
+
23
+ # Check if we're in a git repository
24
+ if ! git rev-parse --git-dir > /dev/null 2>&1; then
25
+ echo "āŒ Not in a git repository"
26
+ exit 1
27
+ fi
28
+
29
+ # Check if there are uncommitted changes
30
+ if ! git diff --quiet || ! git diff --cached --quiet; then
31
+ echo "šŸ“ Adding all changes to git..."
32
+ git add .
33
+
34
+ if [ $? -ne 0 ]; then
35
+ echo "āŒ Failed to add files to git"
36
+ exit 1
37
+ fi
38
+
39
+ echo "šŸ“ Committing changes..."
40
+ git commit -m "$COMMIT_MESSAGE"
41
+
42
+ if [ $? -ne 0 ]; then
43
+ echo "āŒ Failed to commit changes"
44
+ exit 1
45
+ fi
46
+
47
+ echo "āœ… Changes committed successfully"
48
+ else
49
+ echo "ā„¹ļø No uncommitted changes found"
50
+ fi
51
+
52
+ # Bump version
53
+ echo "šŸ“¦ Bumping $VERSION_TYPE version..."
54
+ npm version $VERSION_TYPE
55
+
56
+ if [ $? -ne 0 ]; then
57
+ echo "āŒ Failed to bump version"
58
+ exit 1
59
+ fi
60
+
61
+ NEW_VERSION=$(node -p "require('./package.json').version")
62
+ echo "āœ… Version bumped to: $NEW_VERSION"
63
+
64
+ # Push to git
65
+ echo "šŸš€ Pushing to git..."
66
+ git push origin HEAD
67
+
68
+ if [ $? -ne 0 ]; then
69
+ echo "āŒ Failed to push to git"
70
+ exit 1
71
+ fi
72
+
73
+ echo "āœ… Pushed to git successfully"
74
+
75
+ # Publish to npm
76
+ echo "šŸ“¤ Publishing to npm..."
77
+ npm publish
78
+
79
+ if [ $? -ne 0 ]; then
80
+ echo "āŒ Failed to publish to npm"
81
+ exit 1
82
+ fi
83
+
84
+ echo "šŸŽ‰ Successfully published version $NEW_VERSION to npm!"
85
+ echo ""
86
+ echo "šŸ“‹ Summary:"
87
+ echo " • Committed: '$COMMIT_MESSAGE'"
88
+ echo " • Version: $NEW_VERSION ($VERSION_TYPE bump)"
89
+ echo " • Git: Pushed to remote"
90
+ echo " • NPM: Published successfully"
@@ -0,0 +1,56 @@
1
+ // Simülasyon: Primary display koordinat hesabı
2
+
3
+ const displays = [
4
+ { name: 'Display 1', x: 0, y: 0, width: 2048, height: 1330, isPrimary: true },
5
+ { name: 'Display 2', x: -3440, y: -56, width: 3440, height: 1440, isPrimary: false }
6
+ ];
7
+
8
+ // Combined frame calculation
9
+ const minX = Math.min(...displays.map(d => d.x));
10
+ const minY = Math.min(...displays.map(d => d.y));
11
+ const maxX = Math.max(...displays.map(d => d.x + d.width));
12
+ const maxY = Math.max(...displays.map(d => d.y + d.height));
13
+
14
+ const combinedFrame = {
15
+ x: minX,
16
+ y: minY,
17
+ width: maxX - minX,
18
+ height: maxY - minY
19
+ };
20
+
21
+ console.log('šŸ“ Display Setup:');
22
+ displays.forEach(d => console.log(` ${d.name}: (${d.x}, ${d.y}) ${d.width}x${d.height} ${d.isPrimary ? '[PRIMARY]' : ''}`));
23
+
24
+ console.log(`\nšŸ“ Combined Frame: (${combinedFrame.x}, ${combinedFrame.y}) ${combinedFrame.width}x${combinedFrame.height}`);
25
+
26
+ // Test primary window
27
+ const primaryWindow = { x: 100, y: 100, width: 1000, height: 800 };
28
+
29
+ const globalOffset = { x: combinedFrame.x, y: combinedFrame.y };
30
+
31
+ const localX = primaryWindow.x - globalOffset.x; // 100 - (-3440) = 3540
32
+ const localY = (combinedFrame.height - (primaryWindow.y - globalOffset.y)) - primaryWindow.height;
33
+
34
+ const localWindowCenterX = localX + (primaryWindow.width / 2); // 3540 + 500 = 4040
35
+ const localWindowCenterY = localY + (primaryWindow.height / 2);
36
+
37
+ console.log(`\nšŸŽÆ Primary Window Test: (${primaryWindow.x}, ${primaryWindow.y}) ${primaryWindow.width}x${primaryWindow.height}`);
38
+ console.log(` GlobalOffset: (${globalOffset.x}, ${globalOffset.y})`);
39
+ console.log(` LocalCoords: (${localX}, ${localY})`);
40
+ console.log(` LocalWindowCenter: (${localWindowCenterX}, ${localWindowCenterY})`);
41
+ console.log(` Expected range for primary: X should be 0-${displays.find(d => d.isPrimary).width}`);
42
+ console.log(` āŒ PROBLEM: LocalX ${localX} is way outside primary display bounds!`);
43
+
44
+ console.log(`\nšŸ’” SOLUTION: Primary display windows should stay at their global positions`);
45
+ console.log(` - Primary windows have global coords that are already correct for overlay`);
46
+ console.log(` - Only secondary display windows need coordinate transformation`);
47
+
48
+ // Test secondary window
49
+ const secondaryWindow = { x: -3340, y: 44, width: 3440, height: 1415 };
50
+ const secLocalX = secondaryWindow.x - globalOffset.x; // -3340 - (-3440) = 100
51
+ const secLocalWindowCenterX = secLocalX + (secondaryWindow.width / 2); // 100 + 1720 = 1820
52
+
53
+ console.log(`\nšŸŽÆ Secondary Window Test: (${secondaryWindow.x}, ${secondaryWindow.y}) ${secondaryWindow.width}x${secondaryWindow.height}`);
54
+ console.log(` LocalCoords: (${secLocalX}, ???)`);
55
+ console.log(` LocalWindowCenter: (${secLocalWindowCenterX}, ???)`);
56
+ console.log(` āœ… This looks correct for secondary display`);
@@ -451,13 +451,47 @@ Napi::Value GetDisplays(const Napi::CallbackInfo& info) {
451
451
  NSArray *screens = [NSScreen screens];
452
452
  NSMutableArray *displays = [NSMutableArray array];
453
453
 
454
+ // Get real CGDirectDisplayIDs first
455
+ CGDirectDisplayID activeDisplays[32];
456
+ uint32_t displayCount;
457
+ CGGetActiveDisplayList(32, activeDisplays, &displayCount);
458
+
454
459
  for (NSUInteger i = 0; i < [screens count]; i++) {
455
460
  NSScreen *screen = [screens objectAtIndex:i];
461
+ NSRect frame = [screen frame];
462
+
463
+ // Find matching CGDirectDisplayID
464
+ CGDirectDisplayID displayID = 0;
465
+ bool isPrimary = false;
466
+
467
+ for (uint32_t j = 0; j < displayCount; j++) {
468
+ CGDirectDisplayID candidateID = activeDisplays[j];
469
+ CGRect displayBounds = CGDisplayBounds(candidateID);
470
+
471
+ if (fabs(frame.origin.x - displayBounds.origin.x) < 1.0 &&
472
+ fabs(frame.origin.y - displayBounds.origin.y) < 1.0 &&
473
+ fabs(frame.size.width - displayBounds.size.width) < 1.0 &&
474
+ fabs(frame.size.height - displayBounds.size.height) < 1.0) {
475
+ displayID = candidateID;
476
+ isPrimary = (candidateID == CGMainDisplayID());
477
+ break;
478
+ }
479
+ }
480
+
481
+ // Fallback if no match found
482
+ if (displayID == 0 && i < displayCount) {
483
+ displayID = activeDisplays[i];
484
+ isPrimary = (displayID == CGMainDisplayID());
485
+ }
486
+
456
487
  NSDictionary *displayInfo = @{
457
- @"id": @(i + 1),
488
+ @"id": @(displayID), // Use real display ID
458
489
  @"name": [NSString stringWithFormat:@"Display %lu", (unsigned long)(i + 1)],
459
- @"width": @((int)screen.frame.size.width),
460
- @"height": @((int)screen.frame.size.height)
490
+ @"width": @((int)frame.size.width),
491
+ @"height": @((int)frame.size.height),
492
+ @"x": @((int)frame.origin.x),
493
+ @"y": @((int)frame.origin.y),
494
+ @"isPrimary": @(isPrimary)
461
495
  };
462
496
  [displays addObject:displayInfo];
463
497
  }
@@ -94,6 +94,8 @@ void updateScreenOverlays();
94
94
 
95
95
  @implementation WindowSelectorOverlayView
96
96
 
97
+ @synthesize globalOriginOffset = _globalOriginOffset;
98
+
97
99
  - (instancetype)initWithFrame:(NSRect)frameRect {
98
100
  self = [super initWithFrame:frameRect];
99
101
  if (self) {
@@ -872,9 +874,25 @@ void updateOverlay() {
872
874
  globalOffset = [overlayView.globalOriginOffset pointValue];
873
875
  }
874
876
 
875
- // Convert global window position to local view position
876
- CGFloat localX = x - globalOffset.x;
877
- CGFloat localY = ([g_overlayView frame].size.height - (y - globalOffset.y)) - height;
877
+ // Determine if this is a primary display window
878
+ BOOL isPrimaryDisplayWindow = (x >= 0 && x <= 2048); // Primary display width
879
+
880
+ CGFloat localX, localY;
881
+ if (isPrimaryDisplayWindow) {
882
+ // Primary display windows: Offset to their position in the combined overlay
883
+ // Primary display starts at (3440, 56) within the combined frame
884
+ localX = x + 3440; // Primary starts 3440px from overlay origin
885
+ localY = ([g_overlayView frame].size.height - (y + 56)) - height; // Y offset for primary
886
+ } else {
887
+ // Secondary display windows: Apply standard coordinate transformation
888
+ localX = x - globalOffset.x;
889
+ localY = ([g_overlayView frame].size.height - (y - globalOffset.y)) - height;
890
+ }
891
+
892
+ NSLog(@"šŸ”§ COORDINATE DEBUG: Window (%d, %d) %dx%d [%@]", (int)x, (int)y, (int)width, (int)height, isPrimaryDisplayWindow ? @"PRIMARY" : @"SECONDARY");
893
+ NSLog(@" GlobalOffset: (%.0f, %.0f)", globalOffset.x, globalOffset.y);
894
+ NSLog(@" LocalCoords: (%.0f, %.0f)", localX, localY);
895
+ NSLog(@" ViewFrame: %.0fx%.0f", [g_overlayView frame].size.width, [g_overlayView frame].size.height);
878
896
 
879
897
  // Update overlay view window info for highlighting
880
898
  [overlayView setWindowInfo:targetWindow];
@@ -986,6 +1004,10 @@ void updateOverlay() {
986
1004
  localWindowCenterX - (buttonSize.width / 2),
987
1005
  localWindowCenterY - (buttonSize.height / 2) // Perfect center of window
988
1006
  );
1007
+
1008
+ NSLog(@" ButtonCalc: WindowCenter(%.0f, %.0f) -> Button(%.0f, %.0f)",
1009
+ localWindowCenterX, localWindowCenterY, buttonCenter.x, buttonCenter.y);
1010
+
989
1011
  [g_selectButton setFrameOrigin:buttonCenter];
990
1012
 
991
1013
  // Position app icon above window center
@@ -1863,7 +1885,10 @@ Napi::Value StartWindowSelection(const Napi::CallbackInfo& info) {
1863
1885
  g_overlayView = [[WindowSelectorOverlayView alloc] initWithFrame:localViewFrame];
1864
1886
 
1865
1887
  // Store the global origin offset for coordinate conversion
1866
- [(WindowSelectorOverlayView *)g_overlayView setValue:[NSValue valueWithPoint:fullScreenFrame.origin] forKey:@"globalOriginOffset"];
1888
+ WindowSelectorOverlayView *overlayView = (WindowSelectorOverlayView *)g_overlayView;
1889
+ overlayView.globalOriginOffset = [NSValue valueWithPoint:fullScreenFrame.origin];
1890
+
1891
+ NSLog(@"šŸ”§ SET GlobalOriginOffset: (%.0f, %.0f)", fullScreenFrame.origin.x, fullScreenFrame.origin.y);
1867
1892
  [g_overlayWindow setContentView:g_overlayView];
1868
1893
 
1869
1894
  // Note: NSWindow doesn't have setWantsLayer method, only NSView does
@@ -0,0 +1,25 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ async function testCoordinateDebug() {
5
+ console.log('šŸ” Testing coordinate debugging...');
6
+
7
+ const selector = new WindowSelector();
8
+
9
+ try {
10
+ console.log('šŸš€ Starting window selection with coordinate debugging...');
11
+ await selector.startSelection();
12
+
13
+ console.log('šŸ“ Move cursor to PRIMARY display window and check console logs');
14
+
15
+ // Let it run for 10 seconds to see debug output
16
+ await new Promise(resolve => setTimeout(resolve, 10000));
17
+
18
+ await selector.stopSelection();
19
+
20
+ } catch (error) {
21
+ console.log(`āŒ Test failed: ${error.message}`);
22
+ }
23
+ }
24
+
25
+ testCoordinateDebug();
@@ -0,0 +1,38 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ async function testFinalCoordinateFix() {
5
+ console.log('šŸŽÆ Testing FINAL coordinate fix...');
6
+
7
+ const recorder = new MacRecorder();
8
+ const displays = await recorder.getDisplays();
9
+
10
+ console.log('šŸ“Š Display setup:');
11
+ displays.forEach(display => {
12
+ console.log(` ${display.name}: (${display.x}, ${display.y}) ${display.width}x${display.height} ${display.isPrimary ? '[PRIMARY]' : ''}`);
13
+ });
14
+
15
+ const selector = new WindowSelector();
16
+
17
+ try {
18
+ console.log('\nšŸš€ Starting window selection with coordinate fix...');
19
+ console.log('šŸ“ Test BOTH displays:');
20
+ console.log(' - Primary display windows should now show buttons correctly');
21
+ console.log(' - Secondary display windows should continue working');
22
+ console.log(' - Look for [PRIMARY] vs [SECONDARY] tags in logs');
23
+
24
+ await selector.startSelection();
25
+
26
+ // Let it run for 20 seconds for thorough testing
27
+ await new Promise(resolve => setTimeout(resolve, 20000));
28
+
29
+ await selector.stopSelection();
30
+
31
+ console.log('āœ… Final coordinate test completed!');
32
+
33
+ } catch (error) {
34
+ console.log(`āŒ Test failed: ${error.message}`);
35
+ }
36
+ }
37
+
38
+ testFinalCoordinateFix();
@@ -0,0 +1,17 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ console.log('šŸ”„ LIVE Primary Display Test - Move cursor NOW!');
5
+ console.log(' - Quickly move to primary display windows');
6
+ console.log(' - Look for [PRIMARY] tags in logs');
7
+
8
+ const selector = new WindowSelector();
9
+
10
+ selector.startSelection().then(() => {
11
+ // Auto-stop after 8 seconds
12
+ setTimeout(() => {
13
+ selector.stopSelection().then(() => {
14
+ process.exit(0);
15
+ });
16
+ }, 8000);
17
+ });
@@ -0,0 +1,33 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ async function testPrimaryWindowDebug() {
5
+ console.log('šŸ” Testing PRIMARY display window debugging...');
6
+
7
+ const recorder = new MacRecorder();
8
+ const displays = await recorder.getDisplays();
9
+
10
+ const primary = displays.find(d => d.isPrimary);
11
+ console.log(`Primary display: ${primary.name} at (${primary.x}, ${primary.y}) ${primary.width}x${primary.height}`);
12
+
13
+ const selector = new WindowSelector();
14
+
15
+ try {
16
+ console.log('šŸš€ Starting window selection...');
17
+ console.log('šŸ“ IMPORTANT: Move cursor to a window ON THE PRIMARY DISPLAY');
18
+ console.log(' - Look for windows at coordinates like (0, 50) or (100, 100)');
19
+ console.log(' - Should see GlobalOffset: (3440, 56) for primary display');
20
+
21
+ await selector.startSelection();
22
+
23
+ // Let it run for 15 seconds to catch primary display windows
24
+ await new Promise(resolve => setTimeout(resolve, 15000));
25
+
26
+ await selector.stopSelection();
27
+
28
+ } catch (error) {
29
+ console.log(`āŒ Test failed: ${error.message}`);
30
+ }
31
+ }
32
+
33
+ testPrimaryWindowDebug();
@@ -0,0 +1,88 @@
1
+ const MacRecorder = require('./index');
2
+ const WindowSelector = MacRecorder.WindowSelector;
3
+
4
+ async function testWindowSelector() {
5
+ console.log('🪟 Testing FIXED window selector multi-display...');
6
+
7
+ const recorder = new MacRecorder();
8
+ const displays = await recorder.getDisplays();
9
+
10
+ console.log('šŸ“Š Display setup:');
11
+ displays.forEach((display, index) => {
12
+ console.log(` ${display.name}: ${display.resolution} at (${display.x}, ${display.y}) ${display.isPrimary ? '[PRIMARY]' : ''}`);
13
+ });
14
+
15
+ const selector = new WindowSelector();
16
+
17
+ try {
18
+ console.log('\nšŸ” Starting window selection...');
19
+ console.log(' - Test windows on BOTH displays');
20
+ console.log(' - Check if buttons appear correctly positioned');
21
+ console.log(' - Primary display should now work correctly');
22
+
23
+ await selector.startSelection();
24
+
25
+ // Let it run for 20 seconds for thorough testing
26
+ await new Promise(resolve => setTimeout(resolve, 20000));
27
+
28
+ console.log('šŸ›‘ Stopping window selection...');
29
+ await selector.stopSelection();
30
+
31
+ console.log('āœ… Window selector test completed!');
32
+
33
+ } catch (error) {
34
+ console.log(`āŒ Window selector test failed: ${error.message}`);
35
+ console.log(error.stack);
36
+ }
37
+ }
38
+
39
+ async function testSecondaryDisplayRecording() {
40
+ console.log('\nšŸŽ„ Testing secondary display recording...');
41
+
42
+ const recorder = new MacRecorder();
43
+ const displays = await recorder.getDisplays();
44
+
45
+ const secondaryDisplay = displays.find(d => !d.isPrimary);
46
+ if (!secondaryDisplay) {
47
+ console.log('āš ļø No secondary display found');
48
+ return;
49
+ }
50
+
51
+ console.log(`šŸ–„ļø Testing recording on ${secondaryDisplay.name} (ID: ${secondaryDisplay.id})`);
52
+
53
+ try {
54
+ const outputPath = `./test-output/secondary-display-fix-test.mov`;
55
+
56
+ await recorder.startRecording(outputPath, {
57
+ displayId: secondaryDisplay.id,
58
+ captureCursor: true,
59
+ includeMicrophone: false,
60
+ includeSystemAudio: false
61
+ });
62
+
63
+ console.log('āœ… Recording started on secondary display');
64
+
65
+ // Record for 3 seconds
66
+ await new Promise(resolve => setTimeout(resolve, 3000));
67
+
68
+ await recorder.stopRecording();
69
+ console.log('āœ… Recording completed on secondary display');
70
+
71
+ } catch (error) {
72
+ console.log(`āŒ Secondary display recording failed: ${error.message}`);
73
+ }
74
+ }
75
+
76
+ async function runTests() {
77
+ try {
78
+ await testWindowSelector();
79
+ await testSecondaryDisplayRecording();
80
+
81
+ console.log('\nšŸŽ‰ All tests completed!');
82
+
83
+ } catch (error) {
84
+ console.log(`āŒ Test suite failed: ${error.message}`);
85
+ }
86
+ }
87
+
88
+ runTests();
@@ -0,0 +1,58 @@
1
+ // Primary display window button positioning validation
2
+
3
+ console.log('🧮 Primary Display Button Position Validation');
4
+ console.log('='.repeat(50));
5
+
6
+ // Combined frame
7
+ const combinedFrame = { x: -3440, y: -56, width: 5488, height: 1440 };
8
+
9
+ // Test primary window
10
+ const primaryWindow = { x: 100, y: 100, width: 1000, height: 800 };
11
+
12
+ console.log(`Combined frame: (${combinedFrame.x}, ${combinedFrame.y}) ${combinedFrame.width}x${combinedFrame.height}`);
13
+ console.log(`Primary window: (${primaryWindow.x}, ${primaryWindow.y}) ${primaryWindow.width}x${primaryWindow.height}`);
14
+
15
+ // Current calculation
16
+ const isPrimaryDisplayWindow = (primaryWindow.x >= 0 && primaryWindow.x <= 2048);
17
+ console.log(`\nisPrimaryDisplayWindow: ${isPrimaryDisplayWindow}`);
18
+
19
+ if (isPrimaryDisplayWindow) {
20
+ // Current implementation
21
+ const localX = primaryWindow.x + 3440; // 100 + 3440 = 3540
22
+ const localY = (combinedFrame.height - (primaryWindow.y + 56)) - primaryWindow.height; // 1440 - (100 + 56) - 800 = 484
23
+
24
+ console.log(`Local coordinates: (${localX}, ${localY})`);
25
+
26
+ const localWindowCenterX = localX + (primaryWindow.width / 2); // 3540 + 500 = 4040
27
+ const localWindowCenterY = localY + (primaryWindow.height / 2); // 484 + 400 = 884
28
+
29
+ console.log(`Window center: (${localWindowCenterX}, ${localWindowCenterY})`);
30
+
31
+ const buttonX = localWindowCenterX - 100; // 4040 - 100 = 3940
32
+ const buttonY = localWindowCenterY - 30; // 884 - 30 = 854
33
+
34
+ console.log(`Button position: (${buttonX}, ${buttonY})`);
35
+
36
+ // Validate button is within overlay bounds
37
+ const isValid = buttonX >= 0 && buttonX <= combinedFrame.width && buttonY >= 0 && buttonY <= combinedFrame.height;
38
+ console.log(`Button within overlay bounds: ${isValid} āœ…`);
39
+
40
+ // Validate button is within primary display section of overlay
41
+ const primaryOverlayStart = 3440;
42
+ const primaryOverlayEnd = 5488;
43
+ const inPrimarySection = buttonX >= primaryOverlayStart && buttonX <= primaryOverlayEnd;
44
+ console.log(`Button in primary overlay section (${primaryOverlayStart}-${primaryOverlayEnd}): ${inPrimarySection} āœ…`);
45
+
46
+ console.log('\nšŸŽÆ PRIMARY WINDOW BUTTON POSITIONING SHOULD NOW WORK!');
47
+ } else {
48
+ console.log('Not a primary window');
49
+ }
50
+
51
+ console.log('\nšŸ“Š Compare with secondary window:');
52
+ const secondaryWindow = { x: -3340, y: 44, width: 3440, height: 1415 };
53
+ const secLocalX = secondaryWindow.x - combinedFrame.x; // -3340 - (-3440) = 100
54
+ const secCenterX = secLocalX + (secondaryWindow.width / 2); // 100 + 1720 = 1820
55
+ console.log(`Secondary window center: (${secCenterX}, ???)`);
56
+ console.log(`Secondary button position: (${secCenterX - 100}, ???)`);
57
+
58
+ console.log('\nāœ… Both primary and secondary should now have correct button positioning!');