node-mac-recorder 1.2.2 → 1.2.3

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/cursor-data.json CHANGED
@@ -1,93 +1,359 @@
1
1
  [
2
2
  {
3
- "x": 1119,
4
- "y": 1090,
5
- "timestamp": 106,
3
+ "x": 1947,
4
+ "y": 780,
5
+ "timestamp": 85,
6
+ "cursorType": "pointer",
7
+ "type": "move"
8
+ },
9
+ {
10
+ "x": 1950,
11
+ "y": 780,
12
+ "timestamp": 1476,
13
+ "cursorType": "pointer",
14
+ "type": "move"
15
+ },
16
+ {
17
+ "x": 1954,
18
+ "y": 778,
19
+ "timestamp": 1500,
20
+ "cursorType": "pointer",
21
+ "type": "move"
22
+ },
23
+ {
24
+ "x": 1958,
25
+ "y": 777,
26
+ "timestamp": 1518,
27
+ "cursorType": "pointer",
28
+ "type": "move"
29
+ },
30
+ {
31
+ "x": 1963,
32
+ "y": 775,
33
+ "timestamp": 1541,
34
+ "cursorType": "pointer",
35
+ "type": "move"
36
+ },
37
+ {
38
+ "x": 1967,
39
+ "y": 775,
40
+ "timestamp": 1595,
6
41
  "cursorType": "default",
7
42
  "type": "move"
8
43
  },
9
44
  {
10
- "x": 1119,
11
- "y": 1080,
12
- "timestamp": 407,
45
+ "x": 1971,
46
+ "y": 775,
47
+ "timestamp": 1596,
13
48
  "cursorType": "default",
14
49
  "type": "move"
15
50
  },
16
51
  {
17
- "x": 1119,
18
- "y": 1066,
19
- "timestamp": 423,
52
+ "x": 1973,
53
+ "y": 775,
54
+ "timestamp": 1617,
20
55
  "cursorType": "default",
21
56
  "type": "move"
22
57
  },
23
58
  {
24
- "x": 1119,
25
- "y": 1042,
26
- "timestamp": 446,
59
+ "x": 1975,
60
+ "y": 775,
61
+ "timestamp": 1659,
27
62
  "cursorType": "default",
28
63
  "type": "move"
29
64
  },
30
65
  {
31
- "x": 1119,
32
- "y": 968,
33
- "timestamp": 466,
66
+ "x": 1977,
67
+ "y": 775,
68
+ "timestamp": 1679,
69
+ "cursorType": "pointer",
70
+ "type": "move"
71
+ },
72
+ {
73
+ "x": 1979,
74
+ "y": 775,
75
+ "timestamp": 1744,
76
+ "cursorType": "pointer",
77
+ "type": "move"
78
+ },
79
+ {
80
+ "x": 1979,
81
+ "y": 777,
82
+ "timestamp": 1807,
83
+ "cursorType": "pointer",
84
+ "type": "move"
85
+ },
86
+ {
87
+ "x": 1973,
88
+ "y": 782,
89
+ "timestamp": 1828,
34
90
  "cursorType": "default",
35
91
  "type": "move"
36
92
  },
37
93
  {
38
- "x": 1129,
39
- "y": 906,
40
- "timestamp": 487,
94
+ "x": 1968,
95
+ "y": 787,
96
+ "timestamp": 1850,
41
97
  "cursorType": "default",
42
98
  "type": "move"
43
99
  },
44
100
  {
45
- "x": 1153,
46
- "y": 820,
47
- "timestamp": 507,
101
+ "x": 1957,
102
+ "y": 793,
103
+ "timestamp": 1868,
104
+ "cursorType": "pointer",
105
+ "type": "move"
106
+ },
107
+ {
108
+ "x": 1948,
109
+ "y": 799,
110
+ "timestamp": 1891,
111
+ "cursorType": "pointer",
112
+ "type": "move"
113
+ },
114
+ {
115
+ "x": 1943,
116
+ "y": 802,
117
+ "timestamp": 1911,
48
118
  "cursorType": "default",
49
119
  "type": "move"
50
120
  },
51
121
  {
52
- "x": 1168,
53
- "y": 782,
54
- "timestamp": 528,
122
+ "x": 1937,
123
+ "y": 804,
124
+ "timestamp": 1933,
125
+ "cursorType": "default",
126
+ "type": "move"
127
+ },
128
+ {
129
+ "x": 1938,
130
+ "y": 800,
131
+ "timestamp": 2309,
132
+ "cursorType": "default",
133
+ "type": "move"
134
+ },
135
+ {
136
+ "x": 1939,
137
+ "y": 799,
138
+ "timestamp": 2329,
139
+ "cursorType": "pointer",
140
+ "type": "move"
141
+ },
142
+ {
143
+ "x": 1940,
144
+ "y": 797,
145
+ "timestamp": 2435,
146
+ "cursorType": "pointer",
147
+ "type": "move"
148
+ },
149
+ {
150
+ "x": 1941,
151
+ "y": 794,
152
+ "timestamp": 2477,
153
+ "cursorType": "pointer",
154
+ "type": "move"
155
+ },
156
+ {
157
+ "x": 1941,
158
+ "y": 792,
159
+ "timestamp": 2500,
160
+ "cursorType": "pointer",
161
+ "type": "move"
162
+ },
163
+ {
164
+ "x": 1942,
165
+ "y": 788,
166
+ "timestamp": 2518,
167
+ "cursorType": "pointer",
168
+ "type": "move"
169
+ },
170
+ {
171
+ "x": 1943,
172
+ "y": 786,
173
+ "timestamp": 2560,
174
+ "cursorType": "pointer",
175
+ "type": "move"
176
+ },
177
+ {
178
+ "x": 1945,
179
+ "y": 784,
180
+ "timestamp": 2707,
181
+ "cursorType": "pointer",
182
+ "type": "move"
183
+ },
184
+ {
185
+ "x": 1945,
186
+ "y": 796,
187
+ "timestamp": 3544,
188
+ "cursorType": "pointer",
189
+ "type": "move"
190
+ },
191
+ {
192
+ "x": 1945,
193
+ "y": 817,
194
+ "timestamp": 3568,
55
195
  "cursorType": "default",
56
196
  "type": "move"
57
197
  },
58
198
  {
59
- "x": 1176,
60
- "y": 764,
61
- "timestamp": 549,
199
+ "x": 1951,
200
+ "y": 863,
201
+ "timestamp": 3589,
62
202
  "cursorType": "default",
63
203
  "type": "move"
64
204
  },
65
205
  {
66
- "x": 1176,
67
- "y": 764,
68
- "timestamp": 2578,
206
+ "x": 1956,
207
+ "y": 925,
208
+ "timestamp": 3609,
69
209
  "cursorType": "default",
70
- "type": "mousedown"
210
+ "type": "move"
71
211
  },
72
212
  {
73
- "x": 1176,
74
- "y": 764,
75
- "timestamp": 2599,
213
+ "x": 1966,
214
+ "y": 983,
215
+ "timestamp": 3630,
76
216
  "cursorType": "default",
77
217
  "type": "move"
78
218
  },
79
219
  {
80
- "x": 1176,
81
- "y": 764,
82
- "timestamp": 2724,
220
+ "x": 1970,
221
+ "y": 1006,
222
+ "timestamp": 3650,
223
+ "cursorType": "text",
224
+ "type": "move"
225
+ },
226
+ {
227
+ "x": 1978,
228
+ "y": 1042,
229
+ "timestamp": 3675,
83
230
  "cursorType": "default",
84
- "type": "mouseup"
231
+ "type": "move"
85
232
  },
86
233
  {
87
- "x": 1176,
88
- "y": 764,
89
- "timestamp": 2744,
234
+ "x": 1983,
235
+ "y": 1061,
236
+ "timestamp": 3693,
90
237
  "cursorType": "default",
91
238
  "type": "move"
239
+ },
240
+ {
241
+ "x": 1986,
242
+ "y": 1072,
243
+ "timestamp": 3713,
244
+ "cursorType": "text",
245
+ "type": "move"
246
+ },
247
+ {
248
+ "x": 1990,
249
+ "y": 1082,
250
+ "timestamp": 3734,
251
+ "cursorType": "text",
252
+ "type": "move"
253
+ },
254
+ {
255
+ "x": 1991,
256
+ "y": 1086,
257
+ "timestamp": 3755,
258
+ "cursorType": "text",
259
+ "type": "move"
260
+ },
261
+ {
262
+ "x": 1993,
263
+ "y": 1091,
264
+ "timestamp": 3776,
265
+ "cursorType": "text",
266
+ "type": "move"
267
+ },
268
+ {
269
+ "x": 1994,
270
+ "y": 1096,
271
+ "timestamp": 3797,
272
+ "cursorType": "text",
273
+ "type": "move"
274
+ },
275
+ {
276
+ "x": 1995,
277
+ "y": 1099,
278
+ "timestamp": 3818,
279
+ "cursorType": "text",
280
+ "type": "move"
281
+ },
282
+ {
283
+ "x": 1997,
284
+ "y": 1106,
285
+ "timestamp": 3841,
286
+ "cursorType": "text",
287
+ "type": "move"
288
+ },
289
+ {
290
+ "x": 1997,
291
+ "y": 1109,
292
+ "timestamp": 3859,
293
+ "cursorType": "text",
294
+ "type": "move"
295
+ },
296
+ {
297
+ "x": 1998,
298
+ "y": 1116,
299
+ "timestamp": 3882,
300
+ "cursorType": "text",
301
+ "type": "move"
302
+ },
303
+ {
304
+ "x": 2000,
305
+ "y": 1120,
306
+ "timestamp": 3902,
307
+ "cursorType": "text",
308
+ "type": "move"
309
+ },
310
+ {
311
+ "x": 2000,
312
+ "y": 1123,
313
+ "timestamp": 3924,
314
+ "cursorType": "text",
315
+ "type": "move"
316
+ },
317
+ {
318
+ "x": 2001,
319
+ "y": 1126,
320
+ "timestamp": 3945,
321
+ "cursorType": "text",
322
+ "type": "move"
323
+ },
324
+ {
325
+ "x": 2001,
326
+ "y": 1129,
327
+ "timestamp": 3967,
328
+ "cursorType": "text",
329
+ "type": "move"
330
+ },
331
+ {
332
+ "x": 2002,
333
+ "y": 1135,
334
+ "timestamp": 3986,
335
+ "cursorType": "pointer",
336
+ "type": "move"
337
+ },
338
+ {
339
+ "x": 2002,
340
+ "y": 1142,
341
+ "timestamp": 4007,
342
+ "cursorType": "pointer",
343
+ "type": "move"
344
+ },
345
+ {
346
+ "x": 2002,
347
+ "y": 1146,
348
+ "timestamp": 4027,
349
+ "cursorType": "pointer",
350
+ "type": "move"
351
+ },
352
+ {
353
+ "x": 2002,
354
+ "y": 1151,
355
+ "timestamp": 4049,
356
+ "cursorType": "pointer",
357
+ "type": "move"
92
358
  }
93
359
  ]
package/cursor-test.js CHANGED
@@ -1,50 +1,22 @@
1
- const MacRecorder = require("./index");
2
- const path = require("path");
3
- const fs = require("fs");
4
-
5
- async function testCursorCapture() {
6
- console.log("🎯 Cursor Capture Demo\n");
7
-
8
- const recorder = new MacRecorder();
9
- const outputPath = path.join(__dirname, "cursor-data.json");
10
-
11
- try {
12
- // Başlat
13
- await recorder.startCursorCapture(outputPath);
14
- console.log("✅ Kayıt başladı...");
15
-
16
- // 5 saniye bekle
17
- console.log("📱 5 saniye hareket ettirin, tıklayın...");
18
-
19
- for (let i = 5; i > 0; i--) {
20
- process.stdout.write(`⏳ ${i}... `);
21
- await new Promise((resolve) => setTimeout(resolve, 1000));
22
- }
23
- console.log("\n");
24
-
25
- // Durdur
26
- await recorder.stopCursorCapture();
27
- console.log("✅ Kayıt tamamlandı!");
28
-
29
- // Sonuç
30
- if (fs.existsSync(outputPath)) {
31
- const data = JSON.parse(fs.readFileSync(outputPath, "utf8"));
32
- console.log(`📄 ${data.length} event kaydedildi -> ${outputPath}`);
33
-
34
- // Basit istatistik
35
- const clicks = data.filter((d) => d.type === "mousedown").length;
36
- if (clicks > 0) {
37
- console.log(`🖱️ ${clicks} click algılandı`);
38
- }
39
- }
40
- } catch (error) {
41
- console.error("❌ Hata:", error.message);
42
- }
1
+ const MacRecorder = require("./index.js");
2
+
3
+ const recorder = new MacRecorder();
4
+
5
+ console.log("Starting cursor tracking test...");
6
+ console.log(
7
+ "Move your cursor around different applications to test cursor type detection"
8
+ );
9
+ console.log("The test will run for 10 seconds");
10
+
11
+ try {
12
+ recorder.startCursorCapture("./cursor-data.json");
13
+
14
+ setTimeout(() => {
15
+ recorder.stopCursorCapture();
16
+ console.log("Test completed. Check cursor-data.json for results");
17
+ process.exit(0);
18
+ }, 10000);
19
+ } catch (error) {
20
+ console.error("Error during cursor tracking:", error);
21
+ process.exit(1);
43
22
  }
44
-
45
- // Direkt çalıştır
46
- if (require.main === module) {
47
- testCursorCapture().catch(console.error);
48
- }
49
-
50
- module.exports = { testCursorCapture };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -43,47 +43,113 @@ static bool g_leftMouseDown = false;
43
43
  static bool g_rightMouseDown = false;
44
44
  static NSString *g_lastEventType = @"move";
45
45
 
46
- // Cursor type detection helper - gerçek cursor type'ı al
46
+ // Event tap callback
47
+ static CGEventRef eventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *userInfo) {
48
+ return event;
49
+ }
50
+
51
+ // Cursor type detection helper - sistem genelindeki cursor type'ı al
47
52
  NSString* getCursorType() {
48
53
  @autoreleasepool {
49
54
  g_cursorTypeCounter++;
50
55
 
51
56
  @try {
52
- // NSCursor.currentCursor kullanarak gerçek cursor type'ı al
53
- NSCursor *currentCursor = [NSCursor currentCursor];
57
+ // Get current cursor info
58
+ NSCursor *currentCursor = [NSCursor currentSystemCursor];
59
+ NSString *cursorType = @"default";
60
+
61
+ // Get cursor image info
62
+ NSImage *cursorImage = [currentCursor image];
63
+ NSPoint hotSpot = [currentCursor hotSpot];
64
+ NSSize imageSize = [cursorImage size];
54
65
 
55
- if (currentCursor == [NSCursor arrowCursor]) {
56
- g_lastDetectedCursorType = @"default";
57
- return @"default";
58
- } else if (currentCursor == [NSCursor pointingHandCursor]) {
59
- g_lastDetectedCursorType = @"pointer";
66
+ // Check cursor type by comparing with standard cursors
67
+ if ([currentCursor isEqual:[NSCursor pointingHandCursor]] ||
68
+ (hotSpot.x >= 5 && hotSpot.x <= 7 && hotSpot.y >= 0 && hotSpot.y <= 4) ||
69
+ (hotSpot.x >= 12 && hotSpot.x <= 14 && hotSpot.y >= 7 && hotSpot.y <= 9)) {
60
70
  return @"pointer";
61
- } else if (currentCursor == [NSCursor IBeamCursor]) {
62
- g_lastDetectedCursorType = @"text";
71
+ } else if ([currentCursor isEqual:[NSCursor IBeamCursor]] ||
72
+ (hotSpot.x >= 3 && hotSpot.x <= 5 && hotSpot.y >= 8 && hotSpot.y <= 10 &&
73
+ imageSize.width <= 10 && imageSize.height >= 16)) {
63
74
  return @"text";
64
- } else if (currentCursor == [NSCursor openHandCursor]) {
65
- g_lastDetectedCursorType = @"grab";
66
- return @"grab";
67
- } else if (currentCursor == [NSCursor closedHandCursor]) {
68
- g_lastDetectedCursorType = @"grabbing";
69
- return @"grabbing";
70
- } else if (currentCursor == [NSCursor resizeLeftRightCursor]) {
71
- g_lastDetectedCursorType = @"ew-resize";
75
+ } else if ([currentCursor isEqual:[NSCursor resizeLeftRightCursor]]) {
72
76
  return @"ew-resize";
73
- } else if (currentCursor == [NSCursor resizeUpDownCursor]) {
74
- g_lastDetectedCursorType = @"ns-resize";
77
+ } else if ([currentCursor isEqual:[NSCursor resizeUpDownCursor]]) {
75
78
  return @"ns-resize";
76
- } else if (currentCursor == [NSCursor crosshairCursor]) {
77
- g_lastDetectedCursorType = @"crosshair";
78
- return @"crosshair";
79
- } else {
80
- // Bilinmeyen cursor - default olarak dön
81
- g_lastDetectedCursorType = @"default";
82
- return @"default";
79
+ } else if ([currentCursor isEqual:[NSCursor openHandCursor]] ||
80
+ [currentCursor isEqual:[NSCursor closedHandCursor]]) {
81
+ return @"grabbing";
83
82
  }
83
+
84
+ // Check if we're in a drag operation
85
+ CGEventRef event = CGEventCreate(NULL);
86
+ if (event) {
87
+ CGEventType eventType = (CGEventType)CGEventGetType(event);
88
+ if (eventType == kCGEventLeftMouseDragged ||
89
+ eventType == kCGEventRightMouseDragged) {
90
+ CFRelease(event);
91
+ return @"grabbing";
92
+ }
93
+ CFRelease(event);
94
+ }
95
+
96
+ // Get the window under the cursor
97
+ CGPoint cursorPos = CGEventGetLocation(CGEventCreate(NULL));
98
+ AXUIElementRef systemWide = AXUIElementCreateSystemWide();
99
+ AXUIElementRef elementAtPosition = NULL;
100
+ AXError error = AXUIElementCopyElementAtPosition(systemWide, cursorPos.x, cursorPos.y, &elementAtPosition);
101
+
102
+ if (error == kAXErrorSuccess && elementAtPosition) {
103
+ CFStringRef role = NULL;
104
+ error = AXUIElementCopyAttributeValue(elementAtPosition, kAXRoleAttribute, (CFTypeRef*)&role);
105
+
106
+ if (error == kAXErrorSuccess && role) {
107
+ NSString *elementRole = (__bridge_transfer NSString*)role;
108
+
109
+ // Check for clickable elements that should show pointer cursor
110
+ if ([elementRole isEqualToString:@"AXLink"] ||
111
+ [elementRole isEqualToString:@"AXButton"] ||
112
+ [elementRole isEqualToString:@"AXMenuItem"] ||
113
+ [elementRole isEqualToString:@"AXRadioButton"] ||
114
+ [elementRole isEqualToString:@"AXCheckBox"]) {
115
+ return @"pointer";
116
+ }
117
+
118
+ // Check subrole for additional pointer cursor elements
119
+ CFStringRef subrole = NULL;
120
+ error = AXUIElementCopyAttributeValue(elementAtPosition, kAXSubroleAttribute, (CFTypeRef*)&subrole);
121
+ if (error == kAXErrorSuccess && subrole) {
122
+ NSString *elementSubrole = (__bridge_transfer NSString*)subrole;
123
+
124
+ if ([elementSubrole isEqualToString:@"AXClickable"] ||
125
+ [elementSubrole isEqualToString:@"AXDisclosureTriangle"] ||
126
+ [elementSubrole isEqualToString:@"AXToolbarButton"] ||
127
+ [elementSubrole isEqualToString:@"AXCloseButton"] ||
128
+ [elementSubrole isEqualToString:@"AXMinimizeButton"] ||
129
+ [elementSubrole isEqualToString:@"AXZoomButton"]) {
130
+ return @"pointer";
131
+ }
132
+ }
133
+
134
+ // Check for text elements
135
+ if ([elementRole isEqualToString:@"AXTextField"] ||
136
+ [elementRole isEqualToString:@"AXTextArea"] ||
137
+ [elementRole isEqualToString:@"AXStaticText"]) {
138
+ return @"text";
139
+ }
140
+ }
141
+
142
+ CFRelease(elementAtPosition);
143
+ }
144
+
145
+ if (systemWide) {
146
+ CFRelease(systemWide);
147
+ }
148
+
149
+ return cursorType;
150
+
84
151
  } @catch (NSException *exception) {
85
- // Hata durumunda default dön
86
- g_lastDetectedCursorType = @"default";
152
+ NSLog(@"Error in getCursorType: %@", exception);
87
153
  return @"default";
88
154
  }
89
155
  }