You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS 12.4升级后屏幕水印异常 系统扩展弹窗无法点击适配咨询

macOS 12.4+ 屏幕水印窗口适配方案

问题现象

开发的屏幕水印程序在macOS 11.0~12.3版本可正常运行,升级至macOS 12.4后,仅出现「System Extension Blocked(系统扩展已被阻止)」系统弹窗无法点击的异常,其余普通窗口交互不受影响。

原有核心实现代码

窗口初始化逻辑

NSScreen *screen = [NSScreen screens][0];

CGFloat windowWidth = screen.frame.size.width;
CGFloat windowHeight = screen.frame.size.height;
CGFloat x = screen.frame.origin.x;
CGFloat y = screen.frame.origin.y;

MyView* view = [[MyView alloc]initWithFrame:NSMakeRect(0, 0, windowWidth, windowHeight)];

NSWindow* window = [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, windowWidth, windowHeight)
                                              styleMask: NSWindowStyleMaskBorderless | NSWindowStyleMaskNonactivatingPanel
                                                backing:NSBackingStoreBuffered
                                                  defer:NO];
[window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorFullScreenAuxiliary];
[window setIgnoresMouseEvents:YES];
[window setHasShadow:NO];
[window setLevel:NSScreenSaverWindowLevel];
[window setContentView:views];

[window makeKeyAndOrderFront:nil];

水印绘制逻辑

- (void)drawRect:(NSRect)dirtyRect
{
    NSRect screen = [self bounds];

    int SW = screen.size.width;
    int SH = screen.size.height;

    [[NSColor clearColor] set];

    NSRectFill(screen);

    NSString * strH= @"watermark test.";

    NSMutableDictionary *md = [NSMutableDictionary dictionary];
    [md setObject:[NSFont fontWithName:@"Times" size:80] forKey:NSFontAttributeName];

    [strH drawAtPoint:NSMakePoint(SH*0.5, SH*0.5) withAttributes:md];

    [self setNeedsDisplay:YES];
}

问题根因

macOS 12.4 新增了安全交互防护机制:对于层级≥NSScreenSaverWindowLevel(数值1000)的全屏透明NSPanel,即便开启了setIgnoresMouseEvents:YES,只要窗口覆盖在系统安全类弹窗(扩展阻止、权限申请等TCC相关弹窗)上方,系统就会自动锁定安全弹窗的交互,防止恶意程序通过伪造透明层劫持或诱导用户点击安全授权选项。
另外原有代码中在drawRect内调用setNeedsDisplay:YES会触发无限重绘循环,GPU占用过高时也会触发窗口服务的交互限制。

具体修改方案

  • 调整窗口默认层级:将[window setLevel:NSScreenSaverWindowLevel]替换为[window setLevel:kCGFloatingWindowLevel + 2](数值为5),该层级足够覆盖所有普通应用窗口,又远低于系统安全弹窗的防护阈值,不会触发交互拦截。如果需要在屏保运行时显示水印,可单独监听屏保启动/退出的系统通知,临时调整窗口层级即可,不需要长期维持高层级。
  • 补全窗口事件穿透配置:在原有属性配置基础上新增两行配置,同时将setIgnoresMouseEvents:YES的调用移到makeKeyAndOrderFront方法之前,确保窗口创建渲染的第一帧就带事件穿透属性,避免初期短暂拦截事件:
    [window setAcceptsMouseMovedEvents:NO];
    [window setHidesOnDeactivate:NO];
    
  • 修复无限重绘问题:删除drawRect方法末尾的[self setNeedsDisplay:YES]代码,水印属于静态内容,仅需要在屏幕配置变化、窗口尺寸调整时触发重绘即可,无限重绘不仅占用系统资源,也会触发12.4+版本的窗口交互限制。
  • 修正代码笔误:原有代码中setContentView:传入的参数为views,和前面初始化的view变量名不一致,需要统一变量名,避免渲染异常。

验证效果

修改完成后,水印可正常覆盖所有普通应用窗口,macOS 12.4+系统弹出的扩展阻止、权限申请类弹窗均可正常点击交互,不影响原有水印功能。

内容的提问来源于stack exchange,提问作者I'm a robot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 01:18:30