node-mac-recorder 2.22.17 → 2.22.18
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/lib/cursorCapture/polling.js +127 -13
- package/package.json +1 -1
|
@@ -9,9 +9,13 @@ const IS_ELECTRON = !!(
|
|
|
9
9
|
process.versions.electron
|
|
10
10
|
);
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const NATIVE_TEXT_INPUT_SAMPLE_MS = 120;
|
|
13
|
+
const NATIVE_TEXT_INPUT_GRACE_MS = 600;
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const ELECTRON_SYNTH_GRACE_MS = 400;
|
|
16
|
+
const ELECTRON_SYNTH_THROTTLE_MS = 220;
|
|
17
|
+
|
|
18
|
+
const DEFAULT_CURSOR_INTERVAL_MS = IS_ELECTRON ? 50 : 20;
|
|
15
19
|
|
|
16
20
|
function shouldCaptureCursorSample(lastCapturedData, currentData) {
|
|
17
21
|
if (!lastCapturedData) {
|
|
@@ -76,6 +80,96 @@ function transformInputFrameGlobal(ifr, d) {
|
|
|
76
80
|
};
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
function tryAppendSyntheticTextInputRow(recorder, filepath, cursorData, timestamp) {
|
|
84
|
+
if (!IS_ELECTRON) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const ct = cursorData.cursorType || "";
|
|
88
|
+
if (ct !== "text" && ct !== "vertical-text") {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (timestamp < ELECTRON_SYNTH_GRACE_MS) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const wall = Date.now();
|
|
95
|
+
if (
|
|
96
|
+
wall - (recorder._electronSynthWallMs || 0) <
|
|
97
|
+
ELECTRON_SYNTH_THROTTLE_MS
|
|
98
|
+
) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const vx = cursorData.x;
|
|
102
|
+
const vy = cursorData.y;
|
|
103
|
+
if (!Number.isFinite(vx) || !Number.isFinite(vy)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const tiRow = {
|
|
108
|
+
x: vx,
|
|
109
|
+
y: vy,
|
|
110
|
+
timestamp,
|
|
111
|
+
unixTimeMs: wall,
|
|
112
|
+
cursorType: "text",
|
|
113
|
+
type: "textInput",
|
|
114
|
+
caretX: vx,
|
|
115
|
+
caretY: vy,
|
|
116
|
+
inputFrame: {
|
|
117
|
+
x: vx - 1,
|
|
118
|
+
y: vy - 9,
|
|
119
|
+
width: 2,
|
|
120
|
+
height: 18,
|
|
121
|
+
},
|
|
122
|
+
coordinateSystem: cursorData.coordinateSystem,
|
|
123
|
+
recordingType: cursorData.recordingType,
|
|
124
|
+
videoInfo: cursorData.videoInfo || {},
|
|
125
|
+
displayInfo: cursorData.displayInfo || {},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (cursorData.location) {
|
|
129
|
+
tiRow.location = cursorData.location;
|
|
130
|
+
}
|
|
131
|
+
if (cursorData.windowRelative) {
|
|
132
|
+
tiRow.windowRelative = cursorData.windowRelative;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
recorder.cursorCaptureFirstWrite &&
|
|
137
|
+
recorder.cursorCaptureSessionTimestamp
|
|
138
|
+
) {
|
|
139
|
+
tiRow._syncMetadata = {
|
|
140
|
+
videoStartTime: recorder.cursorCaptureSessionTimestamp,
|
|
141
|
+
cursorStartTime: recorder.cursorCaptureStartTime,
|
|
142
|
+
offsetMs:
|
|
143
|
+
recorder.cursorCaptureStartTime -
|
|
144
|
+
recorder.cursorCaptureSessionTimestamp,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const le = recorder._lastTextInputEmitted;
|
|
149
|
+
if (
|
|
150
|
+
le &&
|
|
151
|
+
Math.abs(le.caretX - tiRow.caretX) < 0.75 &&
|
|
152
|
+
Math.abs(le.caretY - tiRow.caretY) < 0.75 &&
|
|
153
|
+
timestamp - le.timestamp < 220
|
|
154
|
+
) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
recorder._lastTextInputEmitted = {
|
|
158
|
+
caretX: tiRow.caretX,
|
|
159
|
+
caretY: tiRow.caretY,
|
|
160
|
+
timestamp,
|
|
161
|
+
};
|
|
162
|
+
recorder._electronSynthWallMs = wall;
|
|
163
|
+
|
|
164
|
+
const jsonString = JSON.stringify(tiRow);
|
|
165
|
+
if (recorder.cursorCaptureFirstWrite) {
|
|
166
|
+
fs.appendFileSync(filepath, jsonString);
|
|
167
|
+
recorder.cursorCaptureFirstWrite = false;
|
|
168
|
+
} else {
|
|
169
|
+
fs.appendFileSync(filepath, "," + jsonString);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
79
173
|
function tryAppendTextInput(
|
|
80
174
|
recorder,
|
|
81
175
|
nativeBinding,
|
|
@@ -83,10 +177,13 @@ function tryAppendTextInput(
|
|
|
83
177
|
position,
|
|
84
178
|
timestamp,
|
|
85
179
|
) {
|
|
180
|
+
if (IS_ELECTRON) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
86
183
|
if (typeof nativeBinding.getTextInputSnapshot !== "function") {
|
|
87
184
|
return;
|
|
88
185
|
}
|
|
89
|
-
if (timestamp <
|
|
186
|
+
if (timestamp < NATIVE_TEXT_INPUT_GRACE_MS) {
|
|
90
187
|
return;
|
|
91
188
|
}
|
|
92
189
|
const ct = position.cursorType || "";
|
|
@@ -94,7 +191,10 @@ function tryAppendTextInput(
|
|
|
94
191
|
return;
|
|
95
192
|
}
|
|
96
193
|
const wall = Date.now();
|
|
97
|
-
if (
|
|
194
|
+
if (
|
|
195
|
+
wall - (recorder._tiSampleWallMs || 0) <
|
|
196
|
+
NATIVE_TEXT_INPUT_SAMPLE_MS
|
|
197
|
+
) {
|
|
98
198
|
return;
|
|
99
199
|
}
|
|
100
200
|
recorder._tiSampleWallMs = wall;
|
|
@@ -194,10 +294,13 @@ function queueDeferredTextInputSample(
|
|
|
194
294
|
position,
|
|
195
295
|
timestamp,
|
|
196
296
|
) {
|
|
297
|
+
if (IS_ELECTRON) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
197
300
|
if (typeof nativeBinding.getTextInputSnapshot !== "function") {
|
|
198
301
|
return;
|
|
199
302
|
}
|
|
200
|
-
if (timestamp <
|
|
303
|
+
if (timestamp < NATIVE_TEXT_INPUT_GRACE_MS) {
|
|
201
304
|
return;
|
|
202
305
|
}
|
|
203
306
|
const ct = position.cursorType || "";
|
|
@@ -230,7 +333,7 @@ function queueDeferredTextInputSample(
|
|
|
230
333
|
|
|
231
334
|
async function startCursorCapture(recorder, nativeBinding, intervalOrFilepath, options = {}) {
|
|
232
335
|
let filepath;
|
|
233
|
-
let interval =
|
|
336
|
+
let interval = DEFAULT_CURSOR_INTERVAL_MS;
|
|
234
337
|
|
|
235
338
|
if (typeof intervalOrFilepath === "number") {
|
|
236
339
|
interval = Math.max(10, intervalOrFilepath);
|
|
@@ -283,6 +386,7 @@ async function startCursorCapture(recorder, nativeBinding, intervalOrFilepath, o
|
|
|
283
386
|
recorder.lastCapturedData = null;
|
|
284
387
|
recorder.cursorCaptureSessionTimestamp = recorder.sessionTimestamp;
|
|
285
388
|
recorder._tiSampleWallMs = 0;
|
|
389
|
+
recorder._electronSynthWallMs = 0;
|
|
286
390
|
recorder._lastTextInputEmitted = null;
|
|
287
391
|
recorder._tiDeferredPending = false;
|
|
288
392
|
|
|
@@ -405,13 +509,22 @@ async function startCursorCapture(recorder, nativeBinding, intervalOrFilepath, o
|
|
|
405
509
|
recorder.lastCapturedData = { ...cursorData };
|
|
406
510
|
}
|
|
407
511
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
512
|
+
if (IS_ELECTRON) {
|
|
513
|
+
tryAppendSyntheticTextInputRow(
|
|
514
|
+
recorder,
|
|
515
|
+
filepath,
|
|
516
|
+
cursorData,
|
|
517
|
+
timestamp,
|
|
518
|
+
);
|
|
519
|
+
} else {
|
|
520
|
+
queueDeferredTextInputSample(
|
|
521
|
+
recorder,
|
|
522
|
+
nativeBinding,
|
|
523
|
+
filepath,
|
|
524
|
+
position,
|
|
525
|
+
timestamp,
|
|
526
|
+
);
|
|
527
|
+
}
|
|
415
528
|
} catch (error) {
|
|
416
529
|
console.error("Cursor capture error:", error);
|
|
417
530
|
}
|
|
@@ -444,6 +557,7 @@ async function stopCursorCapture(recorder) {
|
|
|
444
557
|
recorder.cursorCaptureFirstWrite = true;
|
|
445
558
|
recorder.cursorDisplayInfo = null;
|
|
446
559
|
recorder._tiSampleWallMs = 0;
|
|
560
|
+
recorder._electronSynthWallMs = 0;
|
|
447
561
|
recorder._lastTextInputEmitted = null;
|
|
448
562
|
recorder._tiDeferredPending = false;
|
|
449
563
|
|