Files
cmbone/platform/system.m
T

142 lines
5.1 KiB
Objective-C
Raw Normal View History

2026-07-08 15:13:26 +08:00
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
#import <stdlib.h>
#import <AppKit/AppKit.h>
#import <ApplicationServices/ApplicationServices.h>
#import <Vision/Vision.h>
#import <Foundation/Foundation.h>
#import "system.h"
// ============ 热键相关 ============
// 声明 Go 回调函数
extern void hotKeyCallback(unsigned int keyCode, unsigned int modifiers);
// 定义热键最大数量
#define MAX_HOTKEYS 10
// 保存注册的 HotKeyRef
static EventHotKeyRef hotKeyRefs[MAX_HOTKEYS];
static EventHotKeyID hotKeyIDs[MAX_HOTKEYS];
static int hotKeyCount = 0;
static int handlerInstalled = 0;
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
EventHotKeyID hkID;
GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hkID), NULL, &hkID);
unsigned int keyCode = hkID.id >> 16;
unsigned int modifiers = hkID.id & 0xFFFF;
hotKeyCallback(keyCode, modifiers); // ✅ 正确传值给 Go
return noErr;
}
void InstallHotKeyHandler() {
if (handlerInstalled) return;
EventTypeSpec eventType;
eventType.eventClass = kEventClassKeyboard;
eventType.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(&MyHotKeyHandler, 1, &eventType, NULL, NULL);
handlerInstalled = 1;
}
void RegisterHotKeyDynamic(unsigned int keyCode, unsigned int modifiers) {
InstallHotKeyHandler();
if (hotKeyCount >= MAX_HOTKEYS) return;
EventHotKeyID hkID;
hkID.signature = 'htk1';
hkID.id = (keyCode << 16) | (modifiers & 0xFFFF); // ✅ 编码 keyCode 和 modifiers
RegisterEventHotKey(keyCode, modifiers, hkID, GetApplicationEventTarget(), 0, &hotKeyRefs[hotKeyCount]);
// ✅ 保存 ID
hotKeyIDs[hotKeyCount] = hkID;
hotKeyCount++;
}
void NSAppActivateIgnoringOtherApps() {
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
}
void UnregisterHotKey(unsigned int keyCode, unsigned int modifiers) {
unsigned int targetID = (keyCode << 16) | (modifiers & 0xFFFF);
for (int i = 0; i < hotKeyCount; i++) {
unsigned int existingID = hotKeyIDs[i].id;
if (existingID == targetID) {
// 注销
UnregisterEventHotKey(hotKeyRefs[i]);
// 清理数组(用后面的项覆盖)
for (int j = i; j < hotKeyCount - 1; j++) {
hotKeyRefs[j] = hotKeyRefs[j + 1];
hotKeyIDs[j] = hotKeyIDs[j + 1];
}
hotKeyCount--;
return;
}
}
}
void HideDockIcon(void) {
NSApplication *app = [NSApplication sharedApplication];
[app setActivationPolicy:NSApplicationActivationPolicyProhibited];
}
// ============ OCR功能 ============
const char* VisionOCR(const char* path) {
@autoreleasepool {
NSString* imagePath = [NSString stringWithUTF8String:path];
NSData* imageData = [NSData dataWithContentsOfFile:imagePath];
NSImage* image = [[NSImage alloc] initWithData:imageData];
if (!image) return "Image load failed";
CGImageRef cgRef = [image CGImageForProposedRect:NULL context:nil hints:nil];
if (!cgRef) return "CGImage conversion failed";
VNRecognizeTextRequest *request = [[VNRecognizeTextRequest alloc] init];
request.recognitionLevel = VNRequestTextRecognitionLevelAccurate;
VNImageRequestHandler *handler = [[VNImageRequestHandler alloc] initWithCGImage:cgRef options:@{}];
NSError *error = nil;
[handler performRequests:@[request] error:&error];
if (error) return [[error.localizedDescription UTF8String] copy];
NSMutableString *result = [NSMutableString string];
for (VNRecognizedTextObservation *obs in request.results) {
VNRecognizedText *topCandidate = [[obs topCandidates:1] firstObject];
if (topCandidate) {
[result appendString:topCandidate.string];
[result appendString:@"\n"];
}
}
return strdup([result UTF8String]);
}
}
const char *VisionOCRFromMemory(const void *data, int size) {
@autoreleasepool {
NSData *imageData = [NSData dataWithBytes:data length:size];
NSImage *image = [[NSImage alloc] initWithData:imageData];
CGImageRef cgRef = [image CGImageForProposedRect:nil context:nil hints:nil];
VNRecognizeTextRequest *req = [[VNRecognizeTextRequest alloc] init];
req.recognitionLevel = VNRequestTextRecognitionLevelAccurate;
req.recognitionLanguages = @[@"zh-Hans", @"en-US"];
VNImageRequestHandler *handler = [[VNImageRequestHandler alloc] initWithCGImage:cgRef options:@{}];
NSError *err = nil;
[handler performRequests:@[req] error:&err];
if (err) return strdup([[err localizedDescription] UTF8String]);
NSMutableString *out = [NSMutableString string];
for (VNRecognizedTextObservation *obs in req.results) {
VNRecognizedText *cand = [[obs topCandidates:1] firstObject];
if (cand) {
[out appendString:cand.string];
[out appendString:@"\n"];
}
}
return strdup([out UTF8String]);
}
}