node-mac-recorder 2.16.30 โ†’ 2.16.32

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.
@@ -1,9 +1,7 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(FORCE_AVFOUNDATION=1 node test-sequential.js)",
5
- "Bash(grep:*)",
6
- "Bash(FORCE_AVFOUNDATION=1 node -e \"\nconsole.log(''๐Ÿงช Testing macOS 14/13 coordinate scaling fix...'');\nconst MacRecorder = require(''./index.js'');\nconst recorder = new MacRecorder();\n\nrecorder.startRecording(''/tmp/coordinate-fix-test.mov'')\n .then(success => {\n console.log(''Start result:'', success ? ''โœ… SUCCESS'' : ''โŒ FAILED'');\n if (success) {\n setTimeout(() => {\n recorder.stopRecording().then(() => {\n console.log(''โœ… Recording stopped'');\n const fs = require(''fs'');\n if (fs.existsSync(''/tmp/coordinate-fix-test.mov'')) {\n const size = Math.round(fs.statSync(''/tmp/coordinate-fix-test.mov'').size/1024);\n console.log(''๐Ÿ“น File size:'', size + ''KB'');\n if (size > 100) {\n console.log(''๐ŸŽ‰ macOS 14/13 coordinate fix test SUCCESS!'');\n } else {\n console.log(''โš ๏ธ File too small, may have issues'');\n }\n } else {\n console.log(''โŒ No output file created'');\n }\n });\n }, 3000); // 3 seconds recording\n }\n })\n .catch(console.error);\n\")"
4
+ "Bash(node:*)"
7
5
  ],
8
6
  "deny": [],
9
7
  "ask": []
@@ -0,0 +1,60 @@
1
+ const MacRecorder = require('./index.js');
2
+
3
+ console.log('๐Ÿ” Debugging cursor coordinate scaling issue...\n');
4
+
5
+ const recorder = new MacRecorder();
6
+
7
+ async function testCursorScaling() {
8
+ console.log('Getting display info...');
9
+ const displays = await recorder.getDisplays();
10
+
11
+ displays.forEach((display, index) => {
12
+ console.log(`Display ${index}:`);
13
+ console.log(` Resolution: ${display.resolution}`);
14
+ console.log(` Position: (${display.x}, ${display.y})`);
15
+ console.log(` Primary: ${display.isPrimary}`);
16
+ console.log(` ID: ${display.id}`);
17
+ });
18
+
19
+ console.log('\n๐ŸŽฏ Please move your mouse to different corners and press Enter...');
20
+ console.log('This will help us understand the coordinate mapping issue.\n');
21
+
22
+ const readline = require('readline');
23
+ const rl = readline.createInterface({
24
+ input: process.stdin,
25
+ output: process.stdout
26
+ });
27
+
28
+ let testCount = 0;
29
+ const testPositions = [
30
+ 'Top-Left corner of the display',
31
+ 'Top-Right corner of the display',
32
+ 'Bottom-Left corner of the display',
33
+ 'Bottom-Right corner of the display',
34
+ 'Center of the display'
35
+ ];
36
+
37
+ function nextTest() {
38
+ if (testCount >= testPositions.length) {
39
+ console.log('\nโœ… Test completed!');
40
+ rl.close();
41
+ process.exit(0);
42
+ return;
43
+ }
44
+
45
+ console.log(`\n๐Ÿ“ Test ${testCount + 1}: Move mouse to ${testPositions[testCount]} and press Enter:`);
46
+ rl.question('', () => {
47
+ const position = recorder.getCursorPosition();
48
+ console.log(` Raw cursor position: (${position.rawX || 'N/A'}, ${position.rawY || 'N/A'})`);
49
+ console.log(` Logical cursor position: (${position.x}, ${position.y})`);
50
+ console.log(` Scale factor: ${position.scaleFactor || 'N/A'}x`);
51
+
52
+ testCount++;
53
+ nextTest();
54
+ });
55
+ }
56
+
57
+ nextTest();
58
+ }
59
+
60
+ testCursorScaling().catch(console.error);
@@ -0,0 +1,73 @@
1
+ const MacRecorder = require('./index.js');
2
+
3
+ console.log('๐Ÿงช Testing cursor DPR scaling fixes...\n');
4
+
5
+ const recorder = new MacRecorder();
6
+
7
+ // Test basic cursor position
8
+ console.log('1. Testing basic cursor position:');
9
+ try {
10
+ const position = recorder.getCursorPosition();
11
+ console.log(` Position: (${position.x}, ${position.y})`);
12
+
13
+ // If we have scaling debug info, show it
14
+ if (position.scaleFactor) {
15
+ console.log(` Scale factor: ${position.scaleFactor}x`);
16
+ console.log(` Raw position: (${position.rawX}, ${position.rawY})`);
17
+ console.log(` Logical position: (${position.x}, ${position.y})`);
18
+ }
19
+ } catch (error) {
20
+ console.error(' Error:', error.message);
21
+ }
22
+
23
+ console.log('\n2. Testing display information:');
24
+ recorder.getDisplays().then(displays => {
25
+ displays.forEach((display, index) => {
26
+ console.log(` Display ${index}: ${display.resolution} at (${display.x}, ${display.y})`);
27
+ console.log(` Primary: ${display.isPrimary}, ID: ${display.id}`);
28
+ });
29
+
30
+ console.log('\n3. Testing cursor capture with DPR fix:');
31
+ const outputFile = 'cursor-dpr-test.json';
32
+
33
+ recorder.startCursorCapture(outputFile, 50).then(() => {
34
+ console.log(` โœ… Cursor capture started, saving to ${outputFile}`);
35
+ console.log(' Move your mouse around for 5 seconds...');
36
+
37
+ setTimeout(() => {
38
+ recorder.stopCursorCapture().then(() => {
39
+ console.log(' โœ… Cursor capture stopped');
40
+
41
+ // Read and analyze the captured data
42
+ const fs = require('fs');
43
+ try {
44
+ const data = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
45
+ if (data.length > 0) {
46
+ const first = data[0];
47
+ const last = data[data.length - 1];
48
+
49
+ console.log(` ๐Ÿ“Š Captured ${data.length} cursor events`);
50
+ console.log(` ๐Ÿ“ First: (${first.x}, ${first.y}) ${first.coordinateSystem || 'unknown'}`);
51
+ console.log(` ๐Ÿ“ Last: (${last.x}, ${last.y}) ${last.coordinateSystem || 'unknown'}`);
52
+
53
+ // Check coordinate system
54
+ const hasCoordinateSystem = data.some(d => d.coordinateSystem);
55
+ console.log(` ๐ŸŽฏ Coordinate system info: ${hasCoordinateSystem ? 'Present' : 'Missing'}`);
56
+ } else {
57
+ console.log(' โš ๏ธ No cursor events captured');
58
+ }
59
+ } catch (readError) {
60
+ console.error(' โŒ Error reading capture file:', readError.message);
61
+ }
62
+
63
+ process.exit(0);
64
+ });
65
+ }, 5000);
66
+ }).catch(error => {
67
+ console.error(' โŒ Cursor capture failed:', error.message);
68
+ process.exit(1);
69
+ });
70
+ }).catch(error => {
71
+ console.error(' Error getting displays:', error.message);
72
+ process.exit(1);
73
+ });
@@ -0,0 +1 @@
1
+ []
@@ -0,0 +1,46 @@
1
+ const MacRecorder = require('./index.js');
2
+
3
+ async function testCursorPermissions() {
4
+ console.log('๐Ÿ”’ Testing cursor tracking permissions...\n');
5
+
6
+ const recorder = new MacRecorder();
7
+
8
+ // Check permissions first
9
+ console.log('1. Checking permissions:');
10
+ const permissions = await recorder.checkPermissions();
11
+ console.log(' Screen Recording:', permissions.screenRecording ? 'โœ…' : 'โŒ');
12
+ console.log(' Accessibility:', permissions.accessibility ? 'โœ…' : 'โŒ');
13
+ console.log(' Microphone:', permissions.microphone ? 'โœ…' : 'โŒ');
14
+
15
+ if (permissions.error) {
16
+ console.log(' Error:', permissions.error);
17
+ }
18
+
19
+ console.log('\n2. Testing direct cursor position (no capture):');
20
+ for (let i = 0; i < 5; i++) {
21
+ try {
22
+ const position = recorder.getCursorPosition();
23
+ console.log(` Position ${i+1}: (${position.x}, ${position.y}) - ${position.cursorType}`);
24
+
25
+ if (position.scaleFactor) {
26
+ console.log(` Scale: ${position.scaleFactor}x, Display: (${position.displayInfo?.displayX}, ${position.displayInfo?.displayY})`);
27
+ console.log(` Logical: ${position.displayInfo?.logicalWidth}x${position.displayInfo?.logicalHeight}`);
28
+ console.log(` Physical: ${position.displayInfo?.physicalWidth}x${position.displayInfo?.physicalHeight}`);
29
+ }
30
+
31
+ await new Promise(resolve => setTimeout(resolve, 500));
32
+ } catch (error) {
33
+ console.error(` Error getting position ${i+1}:`, error.message);
34
+ }
35
+ }
36
+
37
+ console.log('\n3. Testing cursor capture status:');
38
+ const status = recorder.getCursorCaptureStatus();
39
+ console.log(' Is Capturing:', status.isCapturing);
40
+ console.log(' Output File:', status.outputFile);
41
+ console.log(' Display Info:', status.displayInfo);
42
+
43
+ process.exit(0);
44
+ }
45
+
46
+ testCursorPermissions().catch(console.error);
@@ -0,0 +1,53 @@
1
+ const MacRecorder = require('./index.js');
2
+
3
+ async function debugCursorScaling() {
4
+ console.log('๐Ÿ” Debugging cursor scaling detection...\n');
5
+
6
+ const recorder = new MacRecorder();
7
+
8
+ // Get all displays
9
+ const displays = await recorder.getDisplays();
10
+ console.log('๐Ÿ“บ Available displays:');
11
+ displays.forEach((display, index) => {
12
+ console.log(` Display ${index}: ID=${display.id}, ${display.resolution} at (${display.x}, ${display.y}), Primary: ${display.isPrimary}`);
13
+ });
14
+
15
+ console.log('\n๐ŸŽฏ Current cursor position analysis:');
16
+ const position = recorder.getCursorPosition();
17
+
18
+ console.log(` Logical position: (${position.x}, ${position.y})`);
19
+ console.log(` Cursor type: ${position.cursorType}`);
20
+ console.log(` Event type: ${position.eventType}`);
21
+
22
+ if (position.scaleFactor) {
23
+ console.log(` Scale factor detected: ${position.scaleFactor}x`);
24
+ if (position.displayInfo) {
25
+ const info = position.displayInfo;
26
+ console.log(` Display bounds: (${info.displayX}, ${info.displayY})`);
27
+ console.log(` Logical size: ${info.logicalWidth}x${info.logicalHeight}`);
28
+ console.log(` Physical size: ${info.physicalWidth}x${info.physicalHeight}`);
29
+ console.log(` Raw position: (${position.rawX}, ${position.rawY})`);
30
+ }
31
+ } else {
32
+ console.log(` โŒ No scale factor detected`);
33
+ console.log(` This could mean:`);
34
+ console.log(` - getDisplayScalingInfo() didn't find the correct display`);
35
+ console.log(` - Display detection logic needs debugging`);
36
+ }
37
+
38
+ // Find which display the cursor is on
39
+ console.log('\n๐Ÿ” Manual display detection:');
40
+ displays.forEach((display, index) => {
41
+ const inX = position.x >= display.x && position.x < display.x + parseInt(display.resolution.split('x')[0]);
42
+ const inY = position.y >= display.y && position.y < display.y + parseInt(display.resolution.split('x')[1]);
43
+ const isInside = inX && inY;
44
+
45
+ console.log(` Display ${index} (${display.resolution}): ${isInside ? 'โœ… CURSOR IS HERE' : 'โŒ'}`);
46
+ console.log(` Bounds: X(${display.x} - ${display.x + parseInt(display.resolution.split('x')[0])}), Y(${display.y} - ${display.y + parseInt(display.resolution.split('x')[1])})`);
47
+ console.log(` Cursor: X(${position.x}), Y(${position.y})`);
48
+ });
49
+
50
+ process.exit(0);
51
+ }
52
+
53
+ debugCursorScaling().catch(console.error);
package/index.js CHANGED
@@ -258,6 +258,9 @@ class MacRecorder extends EventEmitter {
258
258
  y: targetDisplay.y,
259
259
  width: parseInt(targetDisplay.resolution.split("x")[0]),
260
260
  height: parseInt(targetDisplay.resolution.split("x")[1]),
261
+ // Add scaling information for cursor coordinate transformation
262
+ logicalWidth: parseInt(targetDisplay.resolution.split("x")[0]),
263
+ logicalHeight: parseInt(targetDisplay.resolution.split("x")[1]),
261
264
  };
262
265
  }
263
266
 
@@ -292,6 +295,9 @@ class MacRecorder extends EventEmitter {
292
295
  y: targetDisplay.y,
293
296
  width: parseInt(targetDisplay.resolution.split("x")[0]),
294
297
  height: parseInt(targetDisplay.resolution.split("x")[1]),
298
+ // Add scaling information for cursor coordinate transformation
299
+ logicalWidth: parseInt(targetDisplay.resolution.split("x")[0]),
300
+ logicalHeight: parseInt(targetDisplay.resolution.split("x")[1]),
295
301
  };
296
302
  }
297
303
  } catch (error) {
@@ -696,10 +702,32 @@ class MacRecorder extends EventEmitter {
696
702
  let coordinateSystem = "global";
697
703
 
698
704
  if (this.cursorDisplayInfo) {
699
- // Offset'leri รงฤฑkar (display veya window)
700
- // Y koordinat dรถnรผลŸรผmรผ baลŸlangฤฑรงta yapฤฑldฤฑ
701
- x = position.x - this.cursorDisplayInfo.x;
702
- y = position.y - this.cursorDisplayInfo.y;
705
+ // CRITICAL FIX: Handle DPR scaling for cursor coordinates
706
+ // Get scaling information from native cursor position
707
+ const scaleFactor = position.scaleFactor || 1;
708
+ const displayInfo = position.displayInfo;
709
+
710
+ // Convert logical cursor position to physical (if recording uses physical coordinates)
711
+ let physicalX = position.x;
712
+ let physicalY = position.y;
713
+
714
+ if (scaleFactor > 1.1 && displayInfo) {
715
+ // Convert to display-relative logical, then to physical
716
+ const displayRelativeX = position.x - displayInfo.displayX;
717
+ const displayRelativeY = position.y - displayInfo.displayY;
718
+
719
+ // Scale to physical coordinates
720
+ const physicalRelativeX = displayRelativeX * scaleFactor;
721
+ const physicalRelativeY = displayRelativeY * scaleFactor;
722
+
723
+ // Convert back to global physical
724
+ physicalX = displayInfo.displayX + physicalRelativeX;
725
+ physicalY = displayInfo.displayY + physicalRelativeY;
726
+ }
727
+
728
+ // Offset'leri รงฤฑkar (display veya window) - use physical coordinates
729
+ x = physicalX - this.cursorDisplayInfo.x;
730
+ y = physicalY - this.cursorDisplayInfo.y;
703
731
 
704
732
  if (this.cursorDisplayInfo.windowRelative) {
705
733
  // Window-relative koordinatlar
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.16.30",
3
+ "version": "2.16.32",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -20,6 +20,7 @@ static bool g_isFirstWrite = true;
20
20
  // Forward declaration
21
21
  void cursorTimerCallback();
22
22
  void writeToFile(NSDictionary *cursorData);
23
+ NSDictionary* getDisplayScalingInfo(CGPoint globalPoint);
23
24
 
24
25
  // Timer helper class
25
26
  @interface CursorTimerTarget : NSObject
@@ -198,7 +199,19 @@ CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef eve
198
199
  return event;
199
200
  }
200
201
 
201
- CGPoint location = CGEventGetLocation(event);
202
+ CGPoint rawLocation = CGEventGetLocation(event);
203
+
204
+ // Apply DPR scaling correction for Retina displays
205
+ NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
206
+ CGPoint location = rawLocation;
207
+
208
+ if (scalingInfo) {
209
+ CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
210
+ NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
211
+
212
+ // Keep logical coordinates - no scaling needed here
213
+ location = rawLocation;
214
+ }
202
215
  NSDate *currentDate = [NSDate date];
203
216
  NSTimeInterval timestamp = [currentDate timeIntervalSinceDate:g_trackingStartTime] * 1000; // milliseconds
204
217
  NSTimeInterval unixTimeMs = [currentDate timeIntervalSince1970] * 1000; // unix timestamp in milliseconds
@@ -254,13 +267,25 @@ void cursorTimerCallback() {
254
267
  return;
255
268
  }
256
269
 
257
- // CGEventGetLocation direkt global koordinat verir - รงoklu ekran desteฤŸi iรงin daha doฤŸru
270
+ // Get cursor position with DPR scaling correction
258
271
  CGEventRef event = CGEventCreate(NULL);
259
- CGPoint location = CGEventGetLocation(event);
272
+ CGPoint rawLocation = CGEventGetLocation(event);
260
273
  if (event) {
261
274
  CFRelease(event);
262
275
  }
263
276
 
277
+ // Apply DPR scaling correction for Retina displays
278
+ NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
279
+ CGPoint location = rawLocation;
280
+
281
+ if (scalingInfo) {
282
+ CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
283
+ NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
284
+
285
+ // Keep logical coordinates - no scaling needed here
286
+ location = rawLocation;
287
+ }
288
+
264
289
  NSDate *currentDate = [NSDate date];
265
290
  NSTimeInterval timestamp = [currentDate timeIntervalSinceDate:g_trackingStartTime] * 1000; // milliseconds
266
291
  NSTimeInterval unixTimeMs = [currentDate timeIntervalSince1970] * 1000; // unix timestamp in milliseconds
@@ -435,19 +460,100 @@ Napi::Value StopCursorTracking(const Napi::CallbackInfo& info) {
435
460
  }
436
461
  }
437
462
 
463
+ // Helper function to get display scaling info for cursor coordinates
464
+ NSDictionary* getDisplayScalingInfo(CGPoint globalPoint) {
465
+ @try {
466
+ // Get all displays
467
+ uint32_t displayCount;
468
+ CGDirectDisplayID displayIDs[32];
469
+ CGGetActiveDisplayList(32, displayIDs, &displayCount);
470
+
471
+ // Find which display contains this point
472
+ for (uint32_t i = 0; i < displayCount; i++) {
473
+ CGDirectDisplayID displayID = displayIDs[i];
474
+ CGRect displayBounds = CGDisplayBounds(displayID);
475
+
476
+ NSLog(@"๐Ÿ” Display %u: bounds(%.0f,%.0f %.0fx%.0f), cursor(%.0f,%.0f)",
477
+ displayID, displayBounds.origin.x, displayBounds.origin.y,
478
+ displayBounds.size.width, displayBounds.size.height,
479
+ globalPoint.x, globalPoint.y);
480
+
481
+ // CRITICAL FIX: Manual bounds check for better coordinate system compatibility
482
+ BOOL isInBounds = (globalPoint.x >= displayBounds.origin.x &&
483
+ globalPoint.x < displayBounds.origin.x + displayBounds.size.width &&
484
+ globalPoint.y >= displayBounds.origin.y &&
485
+ globalPoint.y < displayBounds.origin.y + displayBounds.size.height);
486
+
487
+ NSLog(@"๐Ÿ” Manual bounds check: %s", isInBounds ? "INSIDE" : "OUTSIDE");
488
+
489
+ // Check if point is within this display
490
+ if (isInBounds) {
491
+ // Get display scaling info
492
+ CGSize logicalSize = displayBounds.size;
493
+ CGSize physicalSize = CGSizeMake(CGDisplayPixelsWide(displayID), CGDisplayPixelsHigh(displayID));
494
+
495
+ NSLog(@"๐Ÿ” Scaling info: logical(%.0fx%.0f) physical(%.0fx%.0f)",
496
+ logicalSize.width, logicalSize.height, physicalSize.width, physicalSize.height);
497
+
498
+ CGFloat scaleX = physicalSize.width / logicalSize.width;
499
+ CGFloat scaleY = physicalSize.height / logicalSize.height;
500
+ CGFloat scaleFactor = MAX(scaleX, scaleY);
501
+
502
+ NSLog(@"๐Ÿ” Scale factors: X=%.2f, Y=%.2f, Final=%.2f", scaleX, scaleY, scaleFactor);
503
+
504
+ return @{
505
+ @"displayID": @(displayID),
506
+ @"logicalSize": [NSValue valueWithSize:NSMakeSize(logicalSize.width, logicalSize.height)],
507
+ @"physicalSize": [NSValue valueWithSize:NSMakeSize(physicalSize.width, physicalSize.height)],
508
+ @"scaleFactor": @(scaleFactor),
509
+ @"displayBounds": [NSValue valueWithRect:NSMakeRect(displayBounds.origin.x, displayBounds.origin.y, displayBounds.size.width, displayBounds.size.height)]
510
+ };
511
+ }
512
+ }
513
+
514
+ // Fallback to main display
515
+ CGDirectDisplayID mainDisplay = CGMainDisplayID();
516
+ CGRect displayBounds = CGDisplayBounds(mainDisplay);
517
+ CGSize logicalSize = displayBounds.size;
518
+ CGSize physicalSize = CGSizeMake(CGDisplayPixelsWide(mainDisplay), CGDisplayPixelsHigh(mainDisplay));
519
+
520
+ return @{
521
+ @"displayID": @(mainDisplay),
522
+ @"logicalSize": [NSValue valueWithSize:NSMakeSize(logicalSize.width, logicalSize.height)],
523
+ @"physicalSize": [NSValue valueWithSize:NSMakeSize(physicalSize.width, physicalSize.height)],
524
+ @"scaleFactor": @(MAX(physicalSize.width / logicalSize.width, physicalSize.height / logicalSize.height)),
525
+ @"displayBounds": [NSValue valueWithRect:NSMakeRect(displayBounds.origin.x, displayBounds.origin.y, displayBounds.size.width, displayBounds.size.height)]
526
+ };
527
+ } @catch (NSException *exception) {
528
+ return nil;
529
+ }
530
+ }
531
+
438
532
  // NAPI Function: Get Current Cursor Position
439
533
  Napi::Value GetCursorPosition(const Napi::CallbackInfo& info) {
440
534
  Napi::Env env = info.Env();
441
535
 
442
536
  @try {
443
- // NSEvent mouseLocation zaten global koordinatlarda (all displays combined)
444
- // CGEventGetLocation kullanarak direkt global koordinat al - daha doฤŸru
537
+ // Get raw cursor position (may be scaled on Retina displays)
445
538
  CGEventRef event = CGEventCreate(NULL);
446
- CGPoint location = CGEventGetLocation(event);
539
+ CGPoint rawLocation = CGEventGetLocation(event);
447
540
  if (event) {
448
541
  CFRelease(event);
449
542
  }
450
543
 
544
+ // Get display scaling information
545
+ NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
546
+ CGPoint logicalLocation = rawLocation;
547
+
548
+ if (scalingInfo) {
549
+ CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
550
+ NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
551
+
552
+ // CGEventGetLocation returns LOGICAL coordinates (correct for JS layer)
553
+ // Keep logical coordinates - transformation happens in JS layer
554
+ logicalLocation = rawLocation;
555
+ }
556
+
451
557
  NSString *cursorType = getCursorType();
452
558
 
453
559
  // Mouse button state'ini kontrol et
@@ -479,11 +585,34 @@ Napi::Value GetCursorPosition(const Napi::CallbackInfo& info) {
479
585
  g_rightMouseDown = currentRightMouseDown;
480
586
 
481
587
  Napi::Object result = Napi::Object::New(env);
482
- result.Set("x", Napi::Number::New(env, (int)location.x));
483
- result.Set("y", Napi::Number::New(env, (int)location.y));
588
+ result.Set("x", Napi::Number::New(env, (int)logicalLocation.x));
589
+ result.Set("y", Napi::Number::New(env, (int)logicalLocation.y));
484
590
  result.Set("cursorType", Napi::String::New(env, [cursorType UTF8String]));
485
591
  result.Set("eventType", Napi::String::New(env, [eventType UTF8String]));
486
592
 
593
+ // Add scaling info for coordinate transformation
594
+ if (scalingInfo) {
595
+ CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
596
+ NSSize logicalSize = [[scalingInfo objectForKey:@"logicalSize"] sizeValue];
597
+ NSSize physicalSize = [[scalingInfo objectForKey:@"physicalSize"] sizeValue];
598
+ NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
599
+
600
+ result.Set("scaleFactor", Napi::Number::New(env, scaleFactor));
601
+ result.Set("rawX", Napi::Number::New(env, (int)rawLocation.x));
602
+ result.Set("rawY", Napi::Number::New(env, (int)rawLocation.y));
603
+
604
+ // Add display dimension info for JS coordinate transformation
605
+ Napi::Object displayInfo = Napi::Object::New(env);
606
+ displayInfo.Set("logicalWidth", Napi::Number::New(env, logicalSize.width));
607
+ displayInfo.Set("logicalHeight", Napi::Number::New(env, logicalSize.height));
608
+ displayInfo.Set("physicalWidth", Napi::Number::New(env, physicalSize.width));
609
+ displayInfo.Set("physicalHeight", Napi::Number::New(env, physicalSize.height));
610
+ displayInfo.Set("displayX", Napi::Number::New(env, displayBounds.origin.x));
611
+ displayInfo.Set("displayY", Napi::Number::New(env, displayBounds.origin.y));
612
+
613
+ result.Set("displayInfo", displayInfo);
614
+ }
615
+
487
616
  return result;
488
617
 
489
618
  } @catch (NSException *exception) {