Visual Atomicity in El Capitan

Am still having issues with OS X Cap drawing the window shadows and then the window contents. This time I’m not even doing any serious stuff, just have 5 windows with RTF text in a TextArea, not a lot of RTF either.

I’ve tried all kinds of stuff to get to this work and I’m slapped by the OS every time. I’ve tried hiding the windows and showing them once I’m ready, I’ve tried using NSDisableScreenUpdates and after re-watching the WWDC videos, I’ve even tried NSAnimationContext.beginGrouping (with an end grouping when I’m ready…

All produce the same result, the window shadow draws, then (maybe as long a second) the window content is drawn. When the shadow is drawn, there’s a note appearing in console about how OS X has decided to re-enable updates to the WindowServer.

Any ideas?

This seems to happen more and more frequently, it’s frustrating and amateurish.

Oh… Just figured it out… What a surprise, it’s layer-backed views that’s causing the issue. Turn that off and it works as you’d all expect.

Just wanted to ask if that also happen when you do the same with Xcode and poor swift or objective C. But you have your answer now.

Yes and no; I now know what causes it. However I still want to resolve it, have to use Layer-Backed Views, to clean other visual crap.

Even better solution:
Create a module called “VisualAtomicity” and add two methods:

[code]Sub showWhenReady(extends w as window)
w.hide
wArray.append new weakRef( w )

if myTimer = nil then
myTimer = new timer
myTimer.period = 1
myTimer.mode = 1

addHandler myTimer.action, addressOf timerAction

end if
End Sub
[/code]

[code]Private Sub timerAction(obj as timer)
For each winRef as weakRef in wArray
if winRef <> nil and winRef.value <> nil then window( winRef.value ).show
next

redim wArray( -1 )

removeHandler myTimer.action, addressOf timerAction
myTimer = nil
End Sub
[/code]
Two properties:

Private myTimer As timer Private wArray() As weakRef

Then in the open event of the application, or when opening a document window.

window.showWhenReady

No longer receive the console messages and when the application is ready, all the windows appear at the same time, without drawing their shadow first, then their content.

Is this the black window you see when things are busy when opening a Window or starting up? With the white dots in the corners?

It should help…

No, I was just checking if those black windows are the same as what you’re describing.

When my system/hdd is really busy and can’t keep up, I see those black windows a lot. Even when Xojo’s is starting.

I struggled with that when using the App.Opendocument event. This event starts before the Window is drawn. So processing the dropped documents caused the black windows.
I solved that with using CallLater at 10ms to a method passing the FolderItem.

If this is the same issue as you described, I’m still worried because I understand Timers can skip when the main thread is blocked/busy.

I see those black windows all the time. Even the new Microsoft Office 2016 has them.

I don’t know if it’s exactly the same. The main difference is that you continue to do the loading as usual, but the window remains hidden until the timer is called. In theory this gives the OS time to ensure the buffer is ready before the window appears on the screen.

I can’t say for sure if it will solve the black issue, but in theory I do think it will.

I’ve been thinking about this some more and I think what’s happening is when we call window.show the window server goes “Okay, draw the shadow, now draw the content, oh it’s not ready, too late I’ve drawn the shadow”.

As I’m importing RTF data into the window on open, I’ve added the code from the following page around the code for restoring the RTF. It not only improved the loading time of the application, but also improved the window glitches I was getting.

http://www.realsoftwareblog.com/2012/11/speeding-up-textarea-modifications.html

It’s good to know that even MS struggle with getting a simple thing like windows to open correctly on El Cap. Doesn’t make me feel like an amateur so much.

I must admit that I do consider this to be a sign of the new Apple and their attitude towards bugs, instead of figuring out why this happens and fixing it, they instead give some suggestions to developers on how to work around it. It wasn’t an issue until Yosemite.

My suspicion is that the window layer and drop shadow are rendered in a separate thread, while the content is rendered on the main thread. If the main thread is blocking, the window layer renders the shadow and then requests the contentView to render and blocks until the view is rendered (when the main runloop completes?). It seems Apple has moved a lot of stuff into threads to improve the responsiveness of app windows and built in controls, like checkbox animations.

Place the following in the open event of a new project with no default window set and you’ll see the plain window. The red Background appears after the blocking loop exits.

Comment out the line beginning with “flush” and you’ll get the black “Window” until the loop exits and then the red.

[code]Window1.Show

Declare sub flush lib “Cocoa” selector “flush” (classref as ptr)
declare Function NSClassFromString lib “Cocoa” (classname as CFStringRef) as ptr

flush(NSClassFromString(“CATransaction”))

dim t as integer=Ticks
while ticks-t<200
wend

window1.HasBackColor=true
window1.BackColor=&cff0000[/code]

Anything running in the main thread could block the “animation”… I think the bug is that the OS should be waiting for the window content to render before rendering anything to screen.

That would make sense, it would also explain why this bug exists and why Apple can’t fix it. Thing is, it wasn’t a problem that needed to be fixed, at least not IMHO.

10.11.5 is out, anything change?

I haven’t updated yet, I’m a little afraid too. On the Quartz-Developer mailing list there’s already one person who’s discovered a new bug in El Capitan 10.11.5