claude-code/packages/modifiers-napi/src/index.ts
claude-code-best 7e15974be9 feat: 实现 4 个 NAPI 包 — modifiers/image-processor/audio-capture/url-handler
- modifiers-napi: 使用 Bun FFI 调用 macOS CGEventSourceFlagsState 检测修饰键
- image-processor-napi: 集成 sharp 库,macOS 剪贴板图像读取 (osascript)
- audio-capture-napi: 基于 SoX/arecord 的跨平台音频录制
- url-handler-napi: 完善函数签名(保持 null fallback)
- 修复 image-processor 类型兼容性问题

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 01:07:42 +08:00

69 lines
1.6 KiB
TypeScript

import { dlopen, FFIType, suffix } from "bun:ffi";
const FLAG_SHIFT = 0x20000;
const FLAG_CONTROL = 0x40000;
const FLAG_OPTION = 0x80000;
const FLAG_COMMAND = 0x100000;
const modifierFlags: Record<string, number> = {
shift: FLAG_SHIFT,
control: FLAG_CONTROL,
option: FLAG_OPTION,
command: FLAG_COMMAND,
};
// kCGEventSourceStateCombinedSessionState = 0
const kCGEventSourceStateCombinedSessionState = 0;
let cgEventSourceFlagsState: ((stateID: number) => number) | null = null;
function loadFFI(): void {
if (cgEventSourceFlagsState !== null || process.platform !== "darwin") {
return;
}
try {
const lib = dlopen(
`/System/Library/Frameworks/Carbon.framework/Carbon`,
{
CGEventSourceFlagsState: {
args: [FFIType.i32],
returns: FFIType.u64,
},
}
);
cgEventSourceFlagsState = (stateID: number): number => {
return Number(lib.symbols.CGEventSourceFlagsState(stateID));
};
} catch {
// If loading fails, keep the function null so isModifierPressed returns false
cgEventSourceFlagsState = null;
}
}
export function prewarm(): void {
loadFFI();
}
export function isModifierPressed(modifier: string): boolean {
if (process.platform !== "darwin") {
return false;
}
loadFFI();
if (cgEventSourceFlagsState === null) {
return false;
}
const flag = modifierFlags[modifier];
if (flag === undefined) {
return false;
}
const currentFlags = cgEventSourceFlagsState(
kCGEventSourceStateCombinedSessionState
);
return (currentFlags & flag) !== 0;
}