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
相关产品推荐
相关产品推荐

