Ariver
2026-05-18 8058eb48fe3fd1b37be974b5183df6ffc69bfb2c
VoiceSnapGo/internal/overlay/overlay_darwin.go
@@ -4,8 +4,9 @@
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Cocoa
#cgo LDFLAGS: -framework Cocoa -framework ApplicationServices
#import <Cocoa/Cocoa.h>
#import <ApplicationServices/ApplicationServices.h>
#include <dispatch/dispatch.h>
#include <string.h>
@@ -118,8 +119,8 @@
@end
// ---- Custom NSWindow for drag tracking ----
@interface VoiceSnapOverlayWindow : NSWindow {
// ---- Custom NSPanel for drag tracking ----
@interface VoiceSnapOverlayWindow : NSPanel {
   NSPoint _dragStartOrigin;
}
@end
@@ -148,6 +149,7 @@
}
- (BOOL)canBecomeKeyWindow { return NO; }
- (BOOL)canBecomeMainWindow { return NO; }
@end
@@ -155,6 +157,21 @@
static NSWindow* g_window = nil;
static VoiceSnapOverlayView* g_view = nil;
static NSTimer* g_timer = nil;
static void applyOverlayWindowPolicy(NSWindow* window) {
   if (!window) return;
   [window setLevel:CGWindowLevelForKey(kCGStatusWindowLevelKey)];
   [window setCollectionBehavior:
      NSWindowCollectionBehaviorCanJoinAllSpaces |
      NSWindowCollectionBehaviorStationary |
      NSWindowCollectionBehaviorFullScreenAuxiliary |
      NSWindowCollectionBehaviorTransient |
      NSWindowCollectionBehaviorIgnoresCycle];
   [window setCanHide:NO];
   if ([window isKindOfClass:[NSPanel class]]) {
      [(NSPanel*)window setHidesOnDeactivate:NO];
   }
}
static void animateBars(void) {
   g_state.animTime += 0.033f;
@@ -230,6 +247,7 @@
   }
   if (g_state.fadeTarget > 0 && ![g_window isVisible]) {
      applyOverlayWindowPolicy(g_window);
      [g_window orderFrontRegardless];
   }
@@ -259,17 +277,13 @@
   VoiceSnapOverlayWindow* window = [[VoiceSnapOverlayWindow alloc]
      initWithContentRect:NSMakeRect(0, 0, CAP_W, CAP_H)
      styleMask:NSWindowStyleMaskBorderless
      styleMask:NSWindowStyleMaskBorderless | NSWindowStyleMaskNonactivatingPanel
      backing:NSBackingStoreBuffered
      defer:NO];
   [window setOpaque:NO];
   [window setBackgroundColor:[NSColor clearColor]];
   [window setLevel:NSFloatingWindowLevel];
   [window setCollectionBehavior:
      NSWindowCollectionBehaviorCanJoinAllSpaces |
      NSWindowCollectionBehaviorStationary |
      NSWindowCollectionBehaviorFullScreenAuxiliary];
   applyOverlayWindowPolicy(window);
   [window setIgnoresMouseEvents:NO];
   [window setMovableByWindowBackground:YES];
   [window setHasShadow:NO];
@@ -307,11 +321,19 @@
   g_state.hasPosition = 1;
}
static void doBringOverlayForward(void* ctx) {
   (void)ctx;
   if (!g_window) return;
   applyOverlayWindowPolicy(g_window);
   [g_window orderFrontRegardless];
}
static void overlayShow(void) {
   g_state.fadeTarget = 1.0f;
   if (!g_state.hasPosition) {
      dispatch_async_f(dispatch_get_main_queue(), NULL, doAutoPosition);
   }
   dispatch_async_f(dispatch_get_main_queue(), NULL, doBringOverlayForward);
}
static void overlayHide(void) {