NSView slider with lots of CALayers inside (WindowServer - 100%)

I have an interesting case for you. And need help.

My Mac application has an NSView with many layers and sublayers and sublayers inside. Imagine a Finder window with elements (icons, text labels) ... something like this. Each element has a button, background layer selection.

And everything is fine until you have 1000 of such items.

Now with a lot of these elements, my application stops responding when I try to interact with this view. And the tricky part is that this is not my application that consumes the processor, but WindowServer. It reaches 100%, and the system freezes for some time.

Important Note:

My view is part of the application interface. There is a main window with other views. They also have their own structure.

And I noticed that if I put this view placed on a layer in a separate window, it works fine, without freezes having the same 1000 elements. But it starts to stop the system if I return it back to the main window.

Question

  • What is in my application (views / layers) what makes WindowServer insane?
  • Why does placing this view in a separate window help?

I performed several tests and removed all sublayers for each element, leaving only one or two for each. This reduced the load on the system, but still bad. I turned off all the drawings - just small images for the icons. Did not help.

+5
source share
2 answers

WindowServer The main task is to draw graphics-related things for macOS, which means everything you can see from the whole screen, you have to go through WindowServer and let it draw for you.

There are many reasons WindowServer uses a high processor.

  • You have complex drawing methods in the application. - Try to simplify your drawing method.
  • You have a lot of graphics on your desktop so that WindowServer not only draws your application, but also desktop graphics. - Try cleaning the desktop.
  • Do you have applications that require complex graphic drawing? - Try closing this application.

Until you see your exact code, I cannot tell you why placing elements in a separate window can help. Perhaps the window itself hides something that makes drawing easier?

One of my programs has a lot of graphic elements and animations. But I never came across your problem. How about creating a test project and trying things like that? Sometimes this can help to see a problem with a clearer project structure.

I created a simple demo that has 100 * 100 sublayers in the window. There seems to be no problem.

 import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { @IBOutlet weak var window: NSWindow! func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application self.window.contentView?.wantsLayer = true let size = 10 for i in 0..<10000 { let x = i%100 let y = i/100 let layer = CALayer() layer.frame = NSRect(x: x*size, y: y*size, width: size, height: size) layer.backgroundColor = .random() self.window.contentView?.layer?.addSublayer(layer) } } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } } extension CGFloat { static func random() -> CGFloat { return CGFloat(arc4random()) / CGFloat(UInt32.max) } } extension CGColor { static func random() -> CGColor { return CGColor(red: .random(), green: .random(), blue: .random(), alpha: 1.0) } } 

enter image description here

+3
source

I just found out that if the window is borderless, you will have problems. But creating styleMask NSWindowStyleMaskTitled completely fixes the problem.

Unlimited windows seem to be handled differently.

Now I need to find a way to hide all title controls while retaining the mask. I already did it:

  • added NSFullSizeContentViewWindowMask to window mask
  • added

     self.titlebarAppearsTransparent = YES; self.titleVisibility = NSWindowTitleHidden; 

But the window still displays 3 buttons at the top left.

Any ideas how to hide them?

0
source

Source: https://habr.com/ru/post/1271723/


All Articles