@@ -1212,85 +1212,85 @@ extension MenuBarItemManager {
12121212
12131213 let timeoutTask = Task ( timeout: timeout * count) {
12141214 try await withTaskCancellationHandler {
1215- try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < Void , any Error > ) in
1216- // Store continuation so the outer onCancel handler can resume it directly.
1217- continuationHolder. withLock { $0 = continuation }
1218-
1219- // Listen for the following events at the first location
1220- // and perform the following actions:
1221- //
1222- // - Entry event: Decrement the count and post the real
1223- // event to the second location (handled in EventTap 2).
1224- // - Exit event: Resume the continuation.
1225- //
1226- // These events serve as start (or continue) and stop
1227- // signals, and are discarded.
1228- let eventTap1 = EventTap (
1229- label: " EventTap 1 " ,
1230- type: . null,
1231- location: firstLocation,
1232- placement: . headInsertEventTap,
1233- option: . defaultTap
1234- ) { tap, rEvent in
1235- if rEvent. matches ( entryEvent, byIntegerFields: [ . eventSourceUserData] ) {
1236- count -= 1
1237- event. post ( to: secondLocation)
1238- return nil
1239- }
1240- if rEvent. matches ( exitEvent, byIntegerFields: [ . eventSourceUserData] ) {
1241- tap. disable ( )
1242- if didResume. tryClaimOnce ( ) {
1243- continuation. resume ( )
1215+ try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < Void , any Error > ) in
1216+ // Store continuation so the outer onCancel handler can resume it directly.
1217+ continuationHolder. withLock { $0 = continuation }
1218+
1219+ // Listen for the following events at the first location
1220+ // and perform the following actions:
1221+ //
1222+ // - Entry event: Decrement the count and post the real
1223+ // event to the second location (handled in EventTap 2).
1224+ // - Exit event: Resume the continuation.
1225+ //
1226+ // These events serve as start (or continue) and stop
1227+ // signals, and are discarded.
1228+ let eventTap1 = EventTap (
1229+ label: " EventTap 1 " ,
1230+ type: . null,
1231+ location: firstLocation,
1232+ placement: . headInsertEventTap,
1233+ option: . defaultTap
1234+ ) { tap, rEvent in
1235+ if rEvent. matches ( entryEvent, byIntegerFields: [ . eventSourceUserData] ) {
1236+ count -= 1
1237+ event. post ( to: secondLocation)
1238+ return nil
1239+ }
1240+ if rEvent. matches ( exitEvent, byIntegerFields: [ . eventSourceUserData] ) {
1241+ tap. disable ( )
1242+ if didResume. tryClaimOnce ( ) {
1243+ continuation. resume ( )
1244+ }
1245+ return nil
12441246 }
1245- return nil
1247+ return rEvent
12461248 }
1247- return rEvent
1248- }
12491249
1250- // Listen for the real event at the second location and,
1251- // depending on the count, post either the entry or exit
1252- // event to the first location (handled in EventTap 1).
1253- let eventTap2 = EventTap (
1254- label: " EventTap 2 " ,
1255- type: event. type,
1256- location: secondLocation,
1257- placement: . tailAppendEventTap,
1258- option: . listenOnly
1259- ) { tap, rEvent in
1260- guard rEvent. matches ( event, byIntegerFields: CGEventField . menuBarItemEventFields) else {
1250+ // Listen for the real event at the second location and,
1251+ // depending on the count, post either the entry or exit
1252+ // event to the first location (handled in EventTap 1).
1253+ let eventTap2 = EventTap (
1254+ label: " EventTap 2 " ,
1255+ type: event. type,
1256+ location: secondLocation,
1257+ placement: . tailAppendEventTap,
1258+ option: . listenOnly
1259+ ) { tap, rEvent in
1260+ guard rEvent. matches ( event, byIntegerFields: CGEventField . menuBarItemEventFields) else {
1261+ return rEvent
1262+ }
1263+ if count <= 0 {
1264+ tap. disable ( )
1265+ exitEvent. post ( to: firstLocation)
1266+ } else {
1267+ entryEvent. post ( to: firstLocation)
1268+ }
1269+ rEvent. setTargetPID ( pid)
12611270 return rEvent
12621271 }
1263- if count <= 0 {
1264- tap. disable ( )
1265- exitEvent. post ( to: firstLocation)
1266- } else {
1267- entryEvent. post ( to: firstLocation)
1268- }
1269- rEvent. setTargetPID ( pid)
1270- return rEvent
1271- }
12721272
1273- // Keep the taps alive.
1274- eventTaps. append ( eventTap1)
1275- eventTaps. append ( eventTap2)
1276-
1277- let innerTask = Task {
1278- await withTaskCancellationHandler {
1279- eventTap1. enable ( )
1280- eventTap2. enable ( )
1281- entryEvent. post ( to: firstLocation)
1282- } onCancel: {
1283- eventTap1. disable ( )
1284- eventTap2. disable ( )
1285- if didResume. tryClaimOnce ( ) {
1286- continuation. resume ( throwing: CancellationError ( ) )
1273+ // Keep the taps alive.
1274+ eventTaps. append ( eventTap1)
1275+ eventTaps. append ( eventTap2)
1276+
1277+ let innerTask = Task {
1278+ await withTaskCancellationHandler {
1279+ eventTap1. enable ( )
1280+ eventTap2. enable ( )
1281+ entryEvent. post ( to: firstLocation)
1282+ } onCancel: {
1283+ eventTap1. disable ( )
1284+ eventTap2. disable ( )
1285+ if didResume. tryClaimOnce ( ) {
1286+ continuation. resume ( throwing: CancellationError ( ) )
1287+ }
12871288 }
12881289 }
1290+ innerTaskHolder. withLock { $0 = innerTask }
1291+ // Handle race: outer task may have been cancelled before innerTask was stored.
1292+ if Task . isCancelled { innerTask. cancel ( ) }
12891293 }
1290- innerTaskHolder. withLock { $0 = innerTask }
1291- // Handle race: outer task may have been cancelled before innerTask was stored.
1292- if Task . isCancelled { innerTask. cancel ( ) }
1293- }
12941294 } onCancel: {
12951295 innerTaskHolder. withLock { $0 } ? . cancel ( )
12961296 // Directly resume the continuation — handles the common case where
@@ -1367,109 +1367,109 @@ extension MenuBarItemManager {
13671367
13681368 let timeoutTask = Task ( timeout: timeout * count) {
13691369 try await withTaskCancellationHandler {
1370- try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < Void , any Error > ) in
1371- // Store continuation so the outer onCancel handler can resume it directly.
1372- continuationHolder. withLock { $0 = continuation }
1373-
1374- // Listen for the following events at the first location
1375- // and perform the following actions:
1376- //
1377- // - Entry event: Decrement the count and post the real
1378- // event to the second location (handled in EventTap 2).
1379- // - Exit event: Resume the continuation.
1380- //
1381- // These events serve as start (or continue) and stop
1382- // signals, and are discarded.
1383- let eventTap1 = EventTap (
1384- label: " EventTap 1 " ,
1385- type: . null,
1386- location: firstLocation,
1387- placement: . headInsertEventTap,
1388- option: . defaultTap
1389- ) { tap, rEvent in
1390- if rEvent. matches ( entryEvent, byIntegerFields: [ . eventSourceUserData] ) {
1391- count -= 1
1392- event. post ( to: secondLocation)
1393- return nil
1394- }
1395- if rEvent. matches ( exitEvent, byIntegerFields: [ . eventSourceUserData] ) {
1396- tap. disable ( )
1397- if didResume. tryClaimOnce ( ) {
1398- continuation. resume ( )
1370+ try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < Void , any Error > ) in
1371+ // Store continuation so the outer onCancel handler can resume it directly.
1372+ continuationHolder. withLock { $0 = continuation }
1373+
1374+ // Listen for the following events at the first location
1375+ // and perform the following actions:
1376+ //
1377+ // - Entry event: Decrement the count and post the real
1378+ // event to the second location (handled in EventTap 2).
1379+ // - Exit event: Resume the continuation.
1380+ //
1381+ // These events serve as start (or continue) and stop
1382+ // signals, and are discarded.
1383+ let eventTap1 = EventTap (
1384+ label: " EventTap 1 " ,
1385+ type: . null,
1386+ location: firstLocation,
1387+ placement: . headInsertEventTap,
1388+ option: . defaultTap
1389+ ) { tap, rEvent in
1390+ if rEvent. matches ( entryEvent, byIntegerFields: [ . eventSourceUserData] ) {
1391+ count -= 1
1392+ event. post ( to: secondLocation)
1393+ return nil
1394+ }
1395+ if rEvent. matches ( exitEvent, byIntegerFields: [ . eventSourceUserData] ) {
1396+ tap. disable ( )
1397+ if didResume. tryClaimOnce ( ) {
1398+ continuation. resume ( )
1399+ }
1400+ return nil
13991401 }
1400- return nil
1402+ return rEvent
14011403 }
1402- return rEvent
1403- }
14041404
1405- // Listen for the real event at the second location and
1406- // post the real event to the first location (handled in
1407- // EventTap 3).
1408- let eventTap2 = EventTap (
1409- label: " EventTap 2 " ,
1410- type: event. type,
1411- location: secondLocation,
1412- placement: . tailAppendEventTap,
1413- option: . listenOnly
1414- ) { tap, rEvent in
1415- guard rEvent. matches ( event, byIntegerFields: CGEventField . menuBarItemEventFields) else {
1405+ // Listen for the real event at the second location and
1406+ // post the real event to the first location (handled in
1407+ // EventTap 3).
1408+ let eventTap2 = EventTap (
1409+ label: " EventTap 2 " ,
1410+ type: event. type,
1411+ location: secondLocation,
1412+ placement: . tailAppendEventTap,
1413+ option: . listenOnly
1414+ ) { tap, rEvent in
1415+ guard rEvent. matches ( event, byIntegerFields: CGEventField . menuBarItemEventFields) else {
1416+ return rEvent
1417+ }
1418+ if count <= 0 {
1419+ tap. disable ( )
1420+ }
1421+ event. post ( to: firstLocation)
1422+ rEvent. setTargetPID ( pid)
14161423 return rEvent
14171424 }
1418- if count <= 0 {
1419- tap. disable ( )
1420- }
1421- event. post ( to: firstLocation)
1422- rEvent. setTargetPID ( pid)
1423- return rEvent
1424- }
14251425
1426- // Listen for the real event at the first location and,
1427- // depending on the count, post either the entry or exit
1428- // event to the first location (handled in EventTap 1).
1429- let eventTap3 = EventTap (
1430- label: " EventTap 3 " ,
1431- type: event. type,
1432- location: firstLocation,
1433- placement: . headInsertEventTap,
1434- option: . listenOnly
1435- ) { tap, rEvent in
1436- guard rEvent. matches ( event, byIntegerFields: CGEventField . menuBarItemEventFields) else {
1426+ // Listen for the real event at the first location and,
1427+ // depending on the count, post either the entry or exit
1428+ // event to the first location (handled in EventTap 1).
1429+ let eventTap3 = EventTap (
1430+ label: " EventTap 3 " ,
1431+ type: event. type,
1432+ location: firstLocation,
1433+ placement: . headInsertEventTap,
1434+ option: . listenOnly
1435+ ) { tap, rEvent in
1436+ guard rEvent. matches ( event, byIntegerFields: CGEventField . menuBarItemEventFields) else {
1437+ return rEvent
1438+ }
1439+ if count <= 0 {
1440+ tap. disable ( )
1441+ exitEvent. post ( to: firstLocation)
1442+ } else {
1443+ entryEvent. post ( to: firstLocation)
1444+ }
1445+ rEvent. setTargetPID ( pid)
14371446 return rEvent
14381447 }
1439- if count <= 0 {
1440- tap. disable ( )
1441- exitEvent. post ( to: firstLocation)
1442- } else {
1443- entryEvent. post ( to: firstLocation)
1444- }
1445- rEvent. setTargetPID ( pid)
1446- return rEvent
1447- }
14481448
1449- // Keep the taps alive.
1450- eventTaps. append ( eventTap1)
1451- eventTaps. append ( eventTap2)
1452- eventTaps. append ( eventTap3)
1453-
1454- let innerTask = Task {
1455- await withTaskCancellationHandler {
1456- eventTap1. enable ( )
1457- eventTap2. enable ( )
1458- eventTap3. enable ( )
1459- entryEvent. post ( to: firstLocation)
1460- } onCancel: {
1461- eventTap1. disable ( )
1462- eventTap2. disable ( )
1463- eventTap3. disable ( )
1464- if didResume. tryClaimOnce ( ) {
1465- continuation. resume ( throwing: CancellationError ( ) )
1449+ // Keep the taps alive.
1450+ eventTaps. append ( eventTap1)
1451+ eventTaps. append ( eventTap2)
1452+ eventTaps. append ( eventTap3)
1453+
1454+ let innerTask = Task {
1455+ await withTaskCancellationHandler {
1456+ eventTap1. enable ( )
1457+ eventTap2. enable ( )
1458+ eventTap3. enable ( )
1459+ entryEvent. post ( to: firstLocation)
1460+ } onCancel: {
1461+ eventTap1. disable ( )
1462+ eventTap2. disable ( )
1463+ eventTap3. disable ( )
1464+ if didResume. tryClaimOnce ( ) {
1465+ continuation. resume ( throwing: CancellationError ( ) )
1466+ }
14661467 }
14671468 }
1469+ innerTaskHolder. withLock { $0 = innerTask }
1470+ // Handle race: outer task may have been cancelled before innerTask was stored.
1471+ if Task . isCancelled { innerTask. cancel ( ) }
14681472 }
1469- innerTaskHolder. withLock { $0 = innerTask }
1470- // Handle race: outer task may have been cancelled before innerTask was stored.
1471- if Task . isCancelled { innerTask. cancel ( ) }
1472- }
14731473 } onCancel: {
14741474 innerTaskHolder. withLock { $0 } ? . cancel ( )
14751475 // Directly resume the continuation — handles the common case where
@@ -2007,7 +2007,7 @@ extension MenuBarItemManager {
20072007 appState. hidEventManager. startAll ( )
20082008 }
20092009
2010- let maxAttempts = 3 // Reduced from 4 to minimize accumulated delay
2010+ let maxAttempts = 3 // Reduced from 4 to minimize accumulated delay
20112011 let attemptStartTime = Date . now
20122012 for n in 1 ... maxAttempts {
20132013 guard !Task. isCancelled else {
0 commit comments