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

macOS Sonoma中透明NSWindow多次重绘后无法穿透点击

macOS Sonoma下透明窗口多次重绘后点击穿透失效的解决方案

问题分析

在macOS Sonoma中,多次调用setNeedsDisplay:YES重绘完全透明的NSWindow后,点击穿透功能失效,但该功能在macOS 13及更早版本正常。这是因为Sonoma对窗口透明度的检测机制或事件处理逻辑进行了调整,多次重绘后系统可能误判窗口内容并非完全透明,从而取消点击穿透。

修复方案

1. 优化drawRect方法,确保完全透明绘制

原drawRect中的冗余代码可能导致合成异常,简化为仅绘制透明填充:

- (void)drawRect:(NSRect)rect 
{
    [[NSColor clearColor] setFill];
    NSRectFill(rect);
}

2. 启用视图层渲染,避免重绘状态异常

为自定义视图启用Core Animation层,确保透明度状态稳定:

NSCustomView *view = [[NSCustomView alloc] initWithFrame:NSMakeRect(0,0,500,600)];
[view setWantsLayer:YES];
view.layer.backgroundColor = [NSColor clearColor].CGColor;
// 保留原有 autoresizing 设置
[view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[view setAutoresizesSubviews:YES];
[window.contentView addSubview:view];

3. 显式维护窗口点击穿透属性

在窗口初始化及重绘后,确保以下属性正确设置,强制系统识别窗口的透明状态:

// 窗口初始化时
[window setIgnoresMouseEvents:YES]; // 启用点击穿透
[window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window setHasShadow:NO];

// 每次重绘后(可选,防止状态被系统覆盖)
- (void)afterRedraw {
    [window setIgnoresMouseEvents:YES];
    [window setOpaque:NO];
    [window displayIfNeeded];
}

4. 重写视图hitTest方法,拦截事件传递

通过重写自定义视图的hitTest:方法,直接返回nil,确保所有点击事件穿透到窗口下方:

- (NSView *)hitTest:(NSPoint)point
{
    // 让所有点击穿透窗口,不被当前视图拦截
    return nil;
}

5. 调整窗口样式掩码(可选)

尝试移除NSFullSizeContentViewWindowMask,仅保留NSBorderlessWindowMask,避免样式冲突:

NSWindowStyleMask styleMask = NSBorderlessWindowMask;

内容的提问来源于stack exchange,提问作者jian.xue

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:14:52