gpt4 book ai didi

macos - 不透明的 NSWindow 和 WindowServer 性能不佳

转载 作者:行者123 更新时间:2023-12-03 17:46:21 25 4
gpt4 key购买 nike

我需要创建非不透明的透明窗口,其中包含不透明的 subview (称为surfaceView)。每个 subview 可以包含数千个 subview (称为controlView)。所以结构一定是这样的:

NSWindow(非不透明)
- NSView(非不透明)(窗口内容 View )
-- NSView(不透明)(SurfaceView)
--- NSView(不透明)(ControlView)

Illustration

问题是,当内部有数千个 controlView 时,WindowServer 会变得过载。看起来窗口中的任何 NSView 都变得不透明。我不明白我必须做什么。

如果 NSWindow 不是不透明的,则 WindowServer 不会过载。但我需要不透明的 window 。这个案例证明了不透明的NSView可以包含很多 subview 并且性能良好。

如果NSWindow有stylemask [.titled, .ressized],则不会出现重载,窗口变得透明(证明性能良好的透明窗口是可能的),但鼠标无法通过窗口的透明部分。 NSWindow 也有来自私有(private)类 NSThemeframe 的圆角。这个解决方案非常脏,因为它需要重新实现鼠标事件并替换私有(private)类中的一些方法。

如果表面是 childWindows 而不是 subview ,则不会发生重载。但在这种情况下,表面不会被主窗口剪辑,小型化动画不起作用,而且实际上该窗口并不是真正的窗口。

我尝试过与 CAlayer、不透明等不同的组合和操作,但它看起来像是一个错误。绝对有可能获得良好的性能,但我不明白如何实现。有什么想法吗?

最佳答案

也许这会对某人有所帮助。这个问题是由两个意想不到的事实组合而成的。

  1. NSWindow 属性 ignoresMouseEvents有非常奇怪的行为。如果此 ignoresMouseEvents 为 true - 窗口对鼠标变得完全透明,如果为 false - 窗口对鼠标变得完全不透明,即使窗口的某些部分是透明的。窗口 ignoresMouseEvents 的默认值为 false,但窍门是,如果您没有更改此属性,则窗口ignoresMouseEvents 的实际行为将有第三个选项 - 窗口在透明状态下对鼠标变得透明部件,这是窗口的默认状态。

所以 ignoresMouseEvents 是一个 bool 值,实际上有三个选项:true、false 以及薛定谔的默认状态(如果您没有更改它)。

  • 如果窗口有透明背景并且窗口内有大量 CALayer,ignoresMouseEvents 的第三个不直观选项会导致 windowServer 意外的 cpu 过载。因此,在某些情况下,windowServer 对鼠标的透明度检查速度非常慢
  • 因此,默认情况下,此代码将使您的 windowServer 在任何鼠标移动时哭泣:

        let window = NSWindow(contentRect: windowrect, styleMask: [.borderless], backing: .buffered, defer: false);
    window.setIsVisible(true);

    window.contentView?.wantsLayer = true;
    window.contentView?.layer?.borderWidth = 1;
    window.backgroundColor = NSColor.clear;

    for _ in 0...5000 {
    let view = NSView(frame: viewrect);
    view.wantsLayer = true;
    view.layer?.backgroundColor = CGColor(gray: 1.0, alpha: 1.0);
    window.contentView?.addSubview(view);
    }

    您的 View 或图层是否不透明并不重要,它们是否是其他 View 的 subview 。但是,如果您添加 window.ignoresMouseEvents = false 或 true,您的 windowServer 将平静下来,但窗口对鼠标变得完全不透明或完全透明。

    解决方案是对鼠标移动时的鼠标实现您自己的窗口透明度检查(使用trackingArea或GlobalMonitor),如果鼠标位于窗口的透明部分,则将ignoresmouseevents设置为true,否则设置为false。幸运的是,鼠标检查的实现很难编写,这会比默认的windowServer方式慢。

    附注抱歉,语言不好。

    关于macos - 不透明的 NSWindow 和 WindowServer 性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59309522/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com