Thread from comp.lang.tcl (no replies yet)
Major update to the macOS port of Tk
Posted on behalf of Marc Culler, there is a major update to the macOS port of Tk available for testing. --- Tk Timeline watchers may have noticed a long chain of commits to the cgimage_with_crossing branch over the last month. This announcement is to explain what has been going on there. In brief, that branch contains a major change to how drawing works in the macOS port of Tk. This change makes drawing in the macOS port work in a way which is much closer to how it works in the other platforms, and much closer to what the generic Tk code expects. The result is better performance and increased stability. The work is based on an idea of Christopher Chavez's. He realized that Apple's Appkit design allowed for an alternative drawing strategy, and wrote a proof-of-concept implementation. I had created a branch containing his implementation a couple of years ago. Recently I (Marc) merged that branch with Tk 9 and then spent a few weeks ironing out wrinkles. Nicolas Bats, Torsten Berg, Steve Landers, and Kevin Walzer kindly offered to help me by testing the new implementation on their apps, some of which provide very challenging environments for Tk. The result of this work is in the cgimage-with-crossing branch. (The branch also includes a fix for ticket [22349fc78a] which is about <Enter> and <Leave> events - hence the reference to crossing in the branch tag.) The five of us are confident that this is a significant improvement. Some highlights are: * Better performance - CPU-intensive apps use about 20% fewer CPU cycles * Better conformance - Most runs of the regression test suite on macOS 14 show no failures. This is not close to being the case for the trunk branch. * Fewer graphical artifacts (and work continues on those that remain.) * Fewer crashes (none that we know of at the moment.) Given that the branch has been tested on large and complex apps - all of which are working well - this is a major step forwards and we’d like to see it tested more widely. To that end, although we are late in the release cycle we are comfortable recommending that this be merged into trunk and made part of beta3. That’s the only way we can guarantee wider testing. Of course, if any issues crop up they will be addressed in a timely manner. If you are a macOS tkchat user please download and try https://www.codebykevin.com/TkChat_Setup_1.5.2.dmg If you want to try the new macOS Tk with your own code and are comfortable building it yourself please checkout and build the Tk cgimage_with_crossing branch The rest of this message gives some more details about the changes. The main difference is that the new drawing strategy does away with the asynchronous drawing via the drawRect method. A macOS app which uses drawRect is supposed to do all of its drawing within the drawRect method, which can only be called by the NSApplication object. The app can request that drawRect be called by setting the viewNeedsDisplay flag, but can not call drawRect. The original design of the macOS Aqua port only partially complied with this strategy. In fact it was possible to obtain a valid graphics context for drawing to the backing layer of a window's contentView even outside of the drawRect method. The original port would do this, e.g. in a widget display proc which is being run as an idle task. But it would also draw in the drawRect method by first generating expose events for all widgets that need updates, then processing those expose events to create idle tasks, then processing all of those idle tasks immediately. Obviously this scheme was not what Tk expected. Nor was it what Apple expected. And Apple put an abrupqt end to half of it with the release of macOS Mojave, which made it impossible to obtain a valid graphics context outside of the drawRect method. When Tk was first built on Mojave, it produced nothing but totally black windows. Eventually this was worked around by arranging that any drawing operation which failed due to an invalid graphics context would be rescheduled and also to modify drawRect to make it (attempt to) run all of those rescheduled idle tasks. With the new macOS code it is once again true that Tk always has a valid graphics context available and hence can draw at any time. It draws into a CGBitmapImageContext which serves as the backing store for a Tk Window. Instead of calling drawRect, it is configured with Apple's other option which is to call updateLayer instead. In the new setup updateLayer installs the CGImage as the CALayer of the ContentView of the NSWindow which hosts the Tk toplevel, causing the contents of the image to appear in the window. It also creates a new CGImage containing a copy of the window in which subsequent drawing operations take place. This allows drawing operations to take place at the expected time and in the expected order. That makes for better stability and less unpredictability. In addition, it removes the overhead that arises from attempting a drawing operation, having it fail due to an invalid graphics context, rescheduling and rerunning the operation. This accounts for the reduced CPU usage. - MarcClick on article to view all threads in comp.lang.tcl