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 +307 -41
- package/cursor-test.js +21 -49
- package/package.json +1 -1
- package/src/cursor_tracker.mm +95 -29
package/cursor-data.json
CHANGED
|
@@ -1,93 +1,359 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
|
-
"x":
|
|
4
|
-
"y":
|
|
5
|
-
"timestamp":
|
|
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":
|
|
11
|
-
"y":
|
|
12
|
-
"timestamp":
|
|
45
|
+
"x": 1971,
|
|
46
|
+
"y": 775,
|
|
47
|
+
"timestamp": 1596,
|
|
13
48
|
"cursorType": "default",
|
|
14
49
|
"type": "move"
|
|
15
50
|
},
|
|
16
51
|
{
|
|
17
|
-
"x":
|
|
18
|
-
"y":
|
|
19
|
-
"timestamp":
|
|
52
|
+
"x": 1973,
|
|
53
|
+
"y": 775,
|
|
54
|
+
"timestamp": 1617,
|
|
20
55
|
"cursorType": "default",
|
|
21
56
|
"type": "move"
|
|
22
57
|
},
|
|
23
58
|
{
|
|
24
|
-
"x":
|
|
25
|
-
"y":
|
|
26
|
-
"timestamp":
|
|
59
|
+
"x": 1975,
|
|
60
|
+
"y": 775,
|
|
61
|
+
"timestamp": 1659,
|
|
27
62
|
"cursorType": "default",
|
|
28
63
|
"type": "move"
|
|
29
64
|
},
|
|
30
65
|
{
|
|
31
|
-
"x":
|
|
32
|
-
"y":
|
|
33
|
-
"timestamp":
|
|
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":
|
|
39
|
-
"y":
|
|
40
|
-
"timestamp":
|
|
94
|
+
"x": 1968,
|
|
95
|
+
"y": 787,
|
|
96
|
+
"timestamp": 1850,
|
|
41
97
|
"cursorType": "default",
|
|
42
98
|
"type": "move"
|
|
43
99
|
},
|
|
44
100
|
{
|
|
45
|
-
"x":
|
|
46
|
-
"y":
|
|
47
|
-
"timestamp":
|
|
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":
|
|
53
|
-
"y":
|
|
54
|
-
"timestamp":
|
|
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":
|
|
60
|
-
"y":
|
|
61
|
-
"timestamp":
|
|
199
|
+
"x": 1951,
|
|
200
|
+
"y": 863,
|
|
201
|
+
"timestamp": 3589,
|
|
62
202
|
"cursorType": "default",
|
|
63
203
|
"type": "move"
|
|
64
204
|
},
|
|
65
205
|
{
|
|
66
|
-
"x":
|
|
67
|
-
"y":
|
|
68
|
-
"timestamp":
|
|
206
|
+
"x": 1956,
|
|
207
|
+
"y": 925,
|
|
208
|
+
"timestamp": 3609,
|
|
69
209
|
"cursorType": "default",
|
|
70
|
-
"type": "
|
|
210
|
+
"type": "move"
|
|
71
211
|
},
|
|
72
212
|
{
|
|
73
|
-
"x":
|
|
74
|
-
"y":
|
|
75
|
-
"timestamp":
|
|
213
|
+
"x": 1966,
|
|
214
|
+
"y": 983,
|
|
215
|
+
"timestamp": 3630,
|
|
76
216
|
"cursorType": "default",
|
|
77
217
|
"type": "move"
|
|
78
218
|
},
|
|
79
219
|
{
|
|
80
|
-
"x":
|
|
81
|
-
"y":
|
|
82
|
-
"timestamp":
|
|
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": "
|
|
231
|
+
"type": "move"
|
|
85
232
|
},
|
|
86
233
|
{
|
|
87
|
-
"x":
|
|
88
|
-
"y":
|
|
89
|
-
"timestamp":
|
|
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
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
package/src/cursor_tracker.mm
CHANGED
|
@@ -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
|
-
//
|
|
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
|
-
//
|
|
53
|
-
NSCursor *currentCursor = [NSCursor
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
62
|
-
|
|
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
|
|
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
|
|
74
|
-
g_lastDetectedCursorType = @"ns-resize";
|
|
77
|
+
} else if ([currentCursor isEqual:[NSCursor resizeUpDownCursor]]) {
|
|
75
78
|
return @"ns-resize";
|
|
76
|
-
} else if (currentCursor
|
|
77
|
-
|
|
78
|
-
return @"
|
|
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
|
-
|
|
86
|
-
g_lastDetectedCursorType = @"default";
|
|
152
|
+
NSLog(@"Error in getCursorType: %@", exception);
|
|
87
153
|
return @"default";
|
|
88
154
|
}
|
|
89
155
|
}
|