node-mac-recorder 1.2.5 → 1.2.7
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-1751364226346.json +1 -0
- package/cursor-data-1751364314136.json +1 -0
- package/index.js +184 -7
- package/package.json +1 -1
- package/src/cursor_tracker.mm +12 -23
- package/cursor-data.json +0 -359
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
package/index.js
CHANGED
|
@@ -32,6 +32,8 @@ class MacRecorder extends EventEmitter {
|
|
|
32
32
|
this.cursorCaptureStartTime = null;
|
|
33
33
|
this.cursorCaptureFirstWrite = true;
|
|
34
34
|
this.lastCapturedData = null;
|
|
35
|
+
this.cursorDisplayInfo = null;
|
|
36
|
+
this.recordingDisplayInfo = null;
|
|
35
37
|
|
|
36
38
|
this.options = {
|
|
37
39
|
includeMicrophone: false, // Default olarak mikrofon kapalı
|
|
@@ -44,6 +46,10 @@ class MacRecorder extends EventEmitter {
|
|
|
44
46
|
displayId: null, // Hangi ekranı kaydedeceği (null = ana ekran)
|
|
45
47
|
windowId: null, // Hangi pencereyi kaydedeceği (null = tam ekran)
|
|
46
48
|
};
|
|
49
|
+
|
|
50
|
+
// Display cache için async initialization
|
|
51
|
+
this.cachedDisplays = null;
|
|
52
|
+
this.refreshDisplayCache();
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/**
|
|
@@ -189,6 +195,16 @@ class MacRecorder extends EventEmitter {
|
|
|
189
195
|
// DisplayId'yi ayarla
|
|
190
196
|
if (targetDisplayId !== null) {
|
|
191
197
|
this.options.displayId = targetDisplayId;
|
|
198
|
+
|
|
199
|
+
// Recording için display bilgisini sakla (cursor capture için)
|
|
200
|
+
const targetDisplay = displays[targetDisplayId];
|
|
201
|
+
this.recordingDisplayInfo = {
|
|
202
|
+
displayId: targetDisplayId,
|
|
203
|
+
x: targetDisplay.x,
|
|
204
|
+
y: targetDisplay.y,
|
|
205
|
+
width: parseInt(targetDisplay.resolution.split("x")[0]),
|
|
206
|
+
height: parseInt(targetDisplay.resolution.split("x")[1]),
|
|
207
|
+
};
|
|
192
208
|
}
|
|
193
209
|
|
|
194
210
|
this.options.captureArea = {
|
|
@@ -210,6 +226,25 @@ class MacRecorder extends EventEmitter {
|
|
|
210
226
|
}
|
|
211
227
|
}
|
|
212
228
|
|
|
229
|
+
// DisplayId manuel ayarlanmışsa display bilgisini sakla
|
|
230
|
+
if (this.options.displayId !== null && !this.recordingDisplayInfo) {
|
|
231
|
+
try {
|
|
232
|
+
const displays = await this.getDisplays();
|
|
233
|
+
if (this.options.displayId < displays.length) {
|
|
234
|
+
const targetDisplay = displays[this.options.displayId];
|
|
235
|
+
this.recordingDisplayInfo = {
|
|
236
|
+
displayId: this.options.displayId,
|
|
237
|
+
x: targetDisplay.x,
|
|
238
|
+
y: targetDisplay.y,
|
|
239
|
+
width: parseInt(targetDisplay.resolution.split("x")[0]),
|
|
240
|
+
height: parseInt(targetDisplay.resolution.split("x")[1]),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.warn("Display bilgisi alınamadı:", error.message);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
213
248
|
// Çıkış dizinini oluştur
|
|
214
249
|
const outputDir = path.dirname(outputPath);
|
|
215
250
|
if (!fs.existsSync(outputDir)) {
|
|
@@ -291,6 +326,7 @@ class MacRecorder extends EventEmitter {
|
|
|
291
326
|
}
|
|
292
327
|
|
|
293
328
|
this.isRecording = false;
|
|
329
|
+
this.recordingDisplayInfo = null;
|
|
294
330
|
|
|
295
331
|
const result = {
|
|
296
332
|
code: success ? 0 : 1,
|
|
@@ -311,6 +347,7 @@ class MacRecorder extends EventEmitter {
|
|
|
311
347
|
resolve(result);
|
|
312
348
|
} catch (error) {
|
|
313
349
|
this.isRecording = false;
|
|
350
|
+
this.recordingDisplayInfo = null;
|
|
314
351
|
if (this.recordingTimer) {
|
|
315
352
|
clearInterval(this.recordingTimer);
|
|
316
353
|
this.recordingTimer = null;
|
|
@@ -458,16 +495,52 @@ class MacRecorder extends EventEmitter {
|
|
|
458
495
|
|
|
459
496
|
/**
|
|
460
497
|
* Cursor capture başlatır - otomatik olarak dosyaya yazmaya başlar
|
|
498
|
+
* Recording başlatılmışsa otomatik olarak display-relative koordinatlar kullanır
|
|
499
|
+
* @param {string} filepath - Cursor data JSON dosya yolu
|
|
461
500
|
*/
|
|
462
|
-
async startCursorCapture(
|
|
463
|
-
|
|
464
|
-
|
|
501
|
+
async startCursorCapture(intervalOrFilepath = 100) {
|
|
502
|
+
let filepath;
|
|
503
|
+
let interval = 20; // Default 50 FPS
|
|
504
|
+
|
|
505
|
+
// Parameter parsing: number = interval, string = filepath
|
|
506
|
+
if (typeof intervalOrFilepath === "number") {
|
|
507
|
+
interval = Math.max(10, intervalOrFilepath); // Min 10ms
|
|
508
|
+
filepath = `cursor-data-${Date.now()}.json`;
|
|
509
|
+
} else if (typeof intervalOrFilepath === "string") {
|
|
510
|
+
filepath = intervalOrFilepath;
|
|
511
|
+
} else {
|
|
512
|
+
throw new Error(
|
|
513
|
+
"Parameter must be interval (number) or filepath (string)"
|
|
514
|
+
);
|
|
465
515
|
}
|
|
466
516
|
|
|
467
517
|
if (this.cursorCaptureInterval) {
|
|
468
518
|
throw new Error("Cursor capture is already running");
|
|
469
519
|
}
|
|
470
520
|
|
|
521
|
+
// Recording başlatılmışsa o display'i kullan, yoksa main display kullan
|
|
522
|
+
if (this.recordingDisplayInfo) {
|
|
523
|
+
this.cursorDisplayInfo = this.recordingDisplayInfo;
|
|
524
|
+
} else {
|
|
525
|
+
// Main display bilgisini al (her zaman relative koordinatlar için)
|
|
526
|
+
try {
|
|
527
|
+
const displays = await this.getDisplays();
|
|
528
|
+
const mainDisplay = displays.find((d) => d.isPrimary) || displays[0];
|
|
529
|
+
if (mainDisplay) {
|
|
530
|
+
this.cursorDisplayInfo = {
|
|
531
|
+
displayId: 0,
|
|
532
|
+
x: mainDisplay.x,
|
|
533
|
+
y: mainDisplay.y,
|
|
534
|
+
width: parseInt(mainDisplay.resolution.split("x")[0]),
|
|
535
|
+
height: parseInt(mainDisplay.resolution.split("x")[1]),
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
} catch (error) {
|
|
539
|
+
console.warn("Main display bilgisi alınamadı:", error.message);
|
|
540
|
+
this.cursorDisplayInfo = null; // Fallback: global koordinatlar
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
471
544
|
return new Promise((resolve, reject) => {
|
|
472
545
|
try {
|
|
473
546
|
// Dosyayı oluştur ve temizle
|
|
@@ -485,9 +558,29 @@ class MacRecorder extends EventEmitter {
|
|
|
485
558
|
const position = nativeBinding.getCursorPosition();
|
|
486
559
|
const timestamp = Date.now() - this.cursorCaptureStartTime;
|
|
487
560
|
|
|
561
|
+
// Global koordinatları display-relative'e çevir
|
|
562
|
+
let x = position.x;
|
|
563
|
+
let y = position.y;
|
|
564
|
+
|
|
565
|
+
if (this.cursorDisplayInfo) {
|
|
566
|
+
// Display offset'lerini çıkar
|
|
567
|
+
x = position.x - this.cursorDisplayInfo.x;
|
|
568
|
+
y = position.y - this.cursorDisplayInfo.y;
|
|
569
|
+
|
|
570
|
+
// Display bounds kontrolü - cursor display dışındaysa kaydetme
|
|
571
|
+
if (
|
|
572
|
+
x < 0 ||
|
|
573
|
+
y < 0 ||
|
|
574
|
+
x >= this.cursorDisplayInfo.width ||
|
|
575
|
+
y >= this.cursorDisplayInfo.height
|
|
576
|
+
) {
|
|
577
|
+
return; // Bu frame'i skip et
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
488
581
|
const cursorData = {
|
|
489
|
-
x:
|
|
490
|
-
y:
|
|
582
|
+
x: x,
|
|
583
|
+
y: y,
|
|
491
584
|
timestamp: timestamp,
|
|
492
585
|
cursorType: position.cursorType,
|
|
493
586
|
type: position.eventType || "move",
|
|
@@ -511,7 +604,7 @@ class MacRecorder extends EventEmitter {
|
|
|
511
604
|
} catch (error) {
|
|
512
605
|
console.error("Cursor capture error:", error);
|
|
513
606
|
}
|
|
514
|
-
},
|
|
607
|
+
}, interval); // Configurable FPS
|
|
515
608
|
|
|
516
609
|
this.emit("cursorCaptureStarted", filepath);
|
|
517
610
|
resolve(true);
|
|
@@ -546,6 +639,7 @@ class MacRecorder extends EventEmitter {
|
|
|
546
639
|
this.lastCapturedData = null;
|
|
547
640
|
this.cursorCaptureStartTime = null;
|
|
548
641
|
this.cursorCaptureFirstWrite = true;
|
|
642
|
+
this.cursorDisplayInfo = null;
|
|
549
643
|
|
|
550
644
|
this.emit("cursorCaptureStopped");
|
|
551
645
|
resolve(true);
|
|
@@ -557,15 +651,97 @@ class MacRecorder extends EventEmitter {
|
|
|
557
651
|
|
|
558
652
|
/**
|
|
559
653
|
* Anlık cursor pozisyonunu ve tipini döndürür
|
|
654
|
+
* Display-relative koordinatlar döner (her zaman pozitif)
|
|
560
655
|
*/
|
|
561
656
|
getCursorPosition() {
|
|
562
657
|
try {
|
|
563
|
-
|
|
658
|
+
const position = nativeBinding.getCursorPosition();
|
|
659
|
+
|
|
660
|
+
// Cursor hangi display'de ise o display'e relative döndür
|
|
661
|
+
return this.getDisplayRelativePositionSync(position);
|
|
564
662
|
} catch (error) {
|
|
565
663
|
throw new Error("Failed to get cursor position: " + error.message);
|
|
566
664
|
}
|
|
567
665
|
}
|
|
568
666
|
|
|
667
|
+
/**
|
|
668
|
+
* Global koordinatları en uygun display'e relative çevirir (sync version)
|
|
669
|
+
*/
|
|
670
|
+
getDisplayRelativePositionSync(position) {
|
|
671
|
+
try {
|
|
672
|
+
// Cache'lenmiş displays'leri kullan
|
|
673
|
+
if (!this.cachedDisplays) {
|
|
674
|
+
// İlk çağrı - global koordinat döndür ve cache başlat
|
|
675
|
+
this.refreshDisplayCache();
|
|
676
|
+
return position;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Cursor hangi display içinde ise onu bul
|
|
680
|
+
for (const display of this.cachedDisplays) {
|
|
681
|
+
const x = parseInt(display.x);
|
|
682
|
+
const y = parseInt(display.y);
|
|
683
|
+
const width = parseInt(display.resolution.split("x")[0]);
|
|
684
|
+
const height = parseInt(display.resolution.split("x")[1]);
|
|
685
|
+
|
|
686
|
+
if (
|
|
687
|
+
position.x >= x &&
|
|
688
|
+
position.x < x + width &&
|
|
689
|
+
position.y >= y &&
|
|
690
|
+
position.y < y + height
|
|
691
|
+
) {
|
|
692
|
+
// Bu display içinde
|
|
693
|
+
return {
|
|
694
|
+
x: position.x - x,
|
|
695
|
+
y: position.y - y,
|
|
696
|
+
cursorType: position.cursorType,
|
|
697
|
+
eventType: position.eventType,
|
|
698
|
+
displayId: display.id,
|
|
699
|
+
displayIndex: this.cachedDisplays.indexOf(display),
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Hiçbir display'de değilse main display'e relative döndür
|
|
705
|
+
const mainDisplay =
|
|
706
|
+
this.cachedDisplays.find((d) => d.isPrimary) || this.cachedDisplays[0];
|
|
707
|
+
if (mainDisplay) {
|
|
708
|
+
return {
|
|
709
|
+
x: position.x - parseInt(mainDisplay.x),
|
|
710
|
+
y: position.y - parseInt(mainDisplay.y),
|
|
711
|
+
cursorType: position.cursorType,
|
|
712
|
+
eventType: position.eventType,
|
|
713
|
+
displayId: mainDisplay.id,
|
|
714
|
+
displayIndex: this.cachedDisplays.indexOf(mainDisplay),
|
|
715
|
+
outsideDisplay: true,
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Fallback: global koordinat
|
|
720
|
+
return position;
|
|
721
|
+
} catch (error) {
|
|
722
|
+
// Hata durumunda global koordinat döndür
|
|
723
|
+
return position;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Display cache'ini refresh eder
|
|
729
|
+
*/
|
|
730
|
+
async refreshDisplayCache() {
|
|
731
|
+
try {
|
|
732
|
+
this.cachedDisplays = await this.getDisplays();
|
|
733
|
+
} catch (error) {
|
|
734
|
+
console.warn("Display cache refresh failed:", error.message);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* getCurrentCursorPosition alias for getCursorPosition (backward compatibility)
|
|
740
|
+
*/
|
|
741
|
+
getCurrentCursorPosition() {
|
|
742
|
+
return this.getCursorPosition();
|
|
743
|
+
}
|
|
744
|
+
|
|
569
745
|
/**
|
|
570
746
|
* Cursor capture durumunu döndürür
|
|
571
747
|
*/
|
|
@@ -574,6 +750,7 @@ class MacRecorder extends EventEmitter {
|
|
|
574
750
|
isCapturing: !!this.cursorCaptureInterval,
|
|
575
751
|
outputFile: this.cursorCaptureFile || null,
|
|
576
752
|
startTime: this.cursorCaptureStartTime || null,
|
|
753
|
+
displayInfo: this.cursorDisplayInfo || null,
|
|
577
754
|
};
|
|
578
755
|
}
|
|
579
756
|
|
package/package.json
CHANGED
package/src/cursor_tracker.mm
CHANGED
|
@@ -251,22 +251,13 @@ void cursorTimerCallback() {
|
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
//
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
mouseLocation = [NSEvent mouseLocation];
|
|
260
|
-
} else {
|
|
261
|
-
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
262
|
-
mouseLocation = [NSEvent mouseLocation];
|
|
263
|
-
});
|
|
254
|
+
// CGEventGetLocation direkt global koordinat verir - çoklu ekran desteği için daha doğru
|
|
255
|
+
CGEventRef event = CGEventCreate(NULL);
|
|
256
|
+
CGPoint location = CGEventGetLocation(event);
|
|
257
|
+
if (event) {
|
|
258
|
+
CFRelease(event);
|
|
264
259
|
}
|
|
265
260
|
|
|
266
|
-
CGDirectDisplayID mainDisplay = CGMainDisplayID();
|
|
267
|
-
size_t displayHeight = CGDisplayPixelsHigh(mainDisplay);
|
|
268
|
-
location = CGPointMake(mouseLocation.x, displayHeight - mouseLocation.y);
|
|
269
|
-
|
|
270
261
|
NSTimeInterval timestamp = [[NSDate date] timeIntervalSinceDate:g_trackingStartTime] * 1000; // milliseconds
|
|
271
262
|
NSString *cursorType = getCursorType();
|
|
272
263
|
|
|
@@ -443,15 +434,13 @@ Napi::Value GetCursorPosition(const Napi::CallbackInfo& info) {
|
|
|
443
434
|
Napi::Env env = info.Env();
|
|
444
435
|
|
|
445
436
|
@try {
|
|
446
|
-
// NSEvent
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
// macOS coordinate system (bottom-left origin) to screen coordinates (top-left origin)
|
|
454
|
-
CGPoint location = CGPointMake(mouseLocation.x, displayHeight - mouseLocation.y);
|
|
437
|
+
// NSEvent mouseLocation zaten global koordinatlarda (all displays combined)
|
|
438
|
+
// CGEventGetLocation kullanarak direkt global koordinat al - daha doğru
|
|
439
|
+
CGEventRef event = CGEventCreate(NULL);
|
|
440
|
+
CGPoint location = CGEventGetLocation(event);
|
|
441
|
+
if (event) {
|
|
442
|
+
CFRelease(event);
|
|
443
|
+
}
|
|
455
444
|
|
|
456
445
|
NSString *cursorType = getCursorType();
|
|
457
446
|
|
package/cursor-data.json
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
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,
|
|
41
|
-
"cursorType": "default",
|
|
42
|
-
"type": "move"
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"x": 1971,
|
|
46
|
-
"y": 775,
|
|
47
|
-
"timestamp": 1596,
|
|
48
|
-
"cursorType": "default",
|
|
49
|
-
"type": "move"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"x": 1973,
|
|
53
|
-
"y": 775,
|
|
54
|
-
"timestamp": 1617,
|
|
55
|
-
"cursorType": "default",
|
|
56
|
-
"type": "move"
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"x": 1975,
|
|
60
|
-
"y": 775,
|
|
61
|
-
"timestamp": 1659,
|
|
62
|
-
"cursorType": "default",
|
|
63
|
-
"type": "move"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
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,
|
|
90
|
-
"cursorType": "default",
|
|
91
|
-
"type": "move"
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"x": 1968,
|
|
95
|
-
"y": 787,
|
|
96
|
-
"timestamp": 1850,
|
|
97
|
-
"cursorType": "default",
|
|
98
|
-
"type": "move"
|
|
99
|
-
},
|
|
100
|
-
{
|
|
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,
|
|
118
|
-
"cursorType": "default",
|
|
119
|
-
"type": "move"
|
|
120
|
-
},
|
|
121
|
-
{
|
|
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,
|
|
195
|
-
"cursorType": "default",
|
|
196
|
-
"type": "move"
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
"x": 1951,
|
|
200
|
-
"y": 863,
|
|
201
|
-
"timestamp": 3589,
|
|
202
|
-
"cursorType": "default",
|
|
203
|
-
"type": "move"
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
"x": 1956,
|
|
207
|
-
"y": 925,
|
|
208
|
-
"timestamp": 3609,
|
|
209
|
-
"cursorType": "default",
|
|
210
|
-
"type": "move"
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
"x": 1966,
|
|
214
|
-
"y": 983,
|
|
215
|
-
"timestamp": 3630,
|
|
216
|
-
"cursorType": "default",
|
|
217
|
-
"type": "move"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
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,
|
|
230
|
-
"cursorType": "default",
|
|
231
|
-
"type": "move"
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
"x": 1983,
|
|
235
|
-
"y": 1061,
|
|
236
|
-
"timestamp": 3693,
|
|
237
|
-
"cursorType": "default",
|
|
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"
|
|
358
|
-
}
|
|
359
|
-
]
|