node-mac-recorder 2.17.13 → 2.17.14
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/package.json +1 -1
- package/src/cursor_tracker.mm +49 -9
package/package.json
CHANGED
package/src/cursor_tracker.mm
CHANGED
|
@@ -43,9 +43,9 @@ static NSTimeInterval g_lastCursorCheckTime = 0;
|
|
|
43
43
|
static int g_sameCursorDetectionCount = 0;
|
|
44
44
|
static NSString *g_pendingCursorType = nil;
|
|
45
45
|
|
|
46
|
-
// Cursor stability constants
|
|
47
|
-
static const NSTimeInterval CURSOR_STABILITY_THRESHOLD = 0.
|
|
48
|
-
static const int CURSOR_CONFIRMATION_COUNT =
|
|
46
|
+
// Cursor stability constants - more responsive
|
|
47
|
+
static const NSTimeInterval CURSOR_STABILITY_THRESHOLD = 0.05; // 50ms (faster response)
|
|
48
|
+
static const int CURSOR_CONFIRMATION_COUNT = 1; // Need 1 detection (more responsive)
|
|
49
49
|
|
|
50
50
|
// Mouse button state tracking
|
|
51
51
|
static bool g_leftMouseDown = false;
|
|
@@ -157,13 +157,48 @@ NSString* getCursorType() {
|
|
|
157
157
|
[elementRole isEqualToString:@"AXSearchField"]) {
|
|
158
158
|
contextualCursorType = @"text";
|
|
159
159
|
}
|
|
160
|
-
// POINTER CURSORS -
|
|
160
|
+
// POINTER CURSORS - interactive elements with broader detection
|
|
161
161
|
else if ([elementRole isEqualToString:@"AXLink"] ||
|
|
162
162
|
[elementRole isEqualToString:@"AXButton"] ||
|
|
163
163
|
[elementRole isEqualToString:@"AXMenuItem"] ||
|
|
164
164
|
[elementRole isEqualToString:@"AXRadioButton"] ||
|
|
165
|
-
[elementRole isEqualToString:@"AXCheckBox"]
|
|
165
|
+
[elementRole isEqualToString:@"AXCheckBox"] ||
|
|
166
|
+
[elementRole isEqualToString:@"AXPopUpButton"] ||
|
|
167
|
+
[elementRole isEqualToString:@"AXTab"]) {
|
|
166
168
|
contextualCursorType = @"pointer";
|
|
169
|
+
|
|
170
|
+
// Also check subroles for links and buttons
|
|
171
|
+
CFStringRef subrole = NULL;
|
|
172
|
+
AXError subroleError = AXUIElementCopyAttributeValue(elementAtPosition, kAXSubroleAttribute, (CFTypeRef*)&subrole);
|
|
173
|
+
if (subroleError == kAXErrorSuccess && subrole) {
|
|
174
|
+
NSString *elementSubrole = (__bridge_transfer NSString*)subrole;
|
|
175
|
+
if ([elementSubrole isEqualToString:@"AXCloseButton"] ||
|
|
176
|
+
[elementSubrole isEqualToString:@"AXMinimizeButton"] ||
|
|
177
|
+
[elementSubrole isEqualToString:@"AXZoomButton"] ||
|
|
178
|
+
[elementSubrole isEqualToString:@"AXToolbarButton"]) {
|
|
179
|
+
contextualCursorType = @"pointer";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// WEB ELEMENTS - for web links that might not show as AXLink
|
|
184
|
+
else if ([elementRole isEqualToString:@"AXGroup"] ||
|
|
185
|
+
[elementRole isEqualToString:@"AXStaticText"]) {
|
|
186
|
+
// Check if it's clickable/has action
|
|
187
|
+
CFArrayRef actions = NULL;
|
|
188
|
+
AXError actionsError = AXUIElementCopyActionNames(elementAtPosition, &actions);
|
|
189
|
+
if (actionsError == kAXErrorSuccess && actions) {
|
|
190
|
+
CFIndex actionCount = CFArrayGetCount(actions);
|
|
191
|
+
for (CFIndex i = 0; i < actionCount; i++) {
|
|
192
|
+
CFStringRef action = (CFStringRef)CFArrayGetValueAtIndex(actions, i);
|
|
193
|
+
NSString *actionStr = (__bridge NSString*)action;
|
|
194
|
+
if ([actionStr isEqualToString:@"AXPress"] ||
|
|
195
|
+
[actionStr isEqualToString:@"AXShowMenu"]) {
|
|
196
|
+
contextualCursorType = @"pointer";
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
CFRelease(actions);
|
|
201
|
+
}
|
|
167
202
|
}
|
|
168
203
|
// WINDOW BORDER RESIZE - critical for resize detection
|
|
169
204
|
else if ([elementRole isEqualToString:@"AXWindow"]) {
|
|
@@ -239,7 +274,7 @@ NSString* getCursorType() {
|
|
|
239
274
|
// Layer 3: Intelligent fusion of NSCursor and contextual results
|
|
240
275
|
NSString *detectedCursorType = @"default";
|
|
241
276
|
|
|
242
|
-
// Priority logic:
|
|
277
|
+
// Priority logic with better fallback:
|
|
243
278
|
// 1. If contextual gives resize cursor, always use it (resize has highest priority)
|
|
244
279
|
if (contextualCursorType != nil &&
|
|
245
280
|
([contextualCursorType hasSuffix:@"resize"] ||
|
|
@@ -247,14 +282,19 @@ NSString* getCursorType() {
|
|
|
247
282
|
[contextualCursorType isEqualToString:@"ns-resize"])) {
|
|
248
283
|
detectedCursorType = contextualCursorType;
|
|
249
284
|
}
|
|
250
|
-
// 2. If NSCursor gives a definitive answer
|
|
285
|
+
// 2. If NSCursor gives a definitive answer, use it
|
|
251
286
|
else if (nsCursorType != nil) {
|
|
252
287
|
detectedCursorType = nsCursorType;
|
|
253
288
|
}
|
|
254
|
-
// 3. If
|
|
255
|
-
else if (contextualCursorType != nil
|
|
289
|
+
// 3. If contextual gives specific non-resize cursor, use it
|
|
290
|
+
else if (contextualCursorType != nil &&
|
|
291
|
+
![contextualCursorType isEqualToString:@"default"]) {
|
|
256
292
|
detectedCursorType = contextualCursorType;
|
|
257
293
|
}
|
|
294
|
+
// 4. If both are nil or default, use true default
|
|
295
|
+
else {
|
|
296
|
+
detectedCursorType = @"default";
|
|
297
|
+
}
|
|
258
298
|
|
|
259
299
|
// Layer 4: Stability filtering to prevent oscillation
|
|
260
300
|
|