Hello, I’m Jonas Holzman, and over this summer I’ll be working on improving the Blender macOS User Interface Experience.
Synopsis
In recent years, Blender support for macOS specific features has drastically improved. With the introduction of the Metal Viewport, features such as HDR support and development support from Apple, Blender can now be easily regarded as one of the best 3D applications available for the Mac. However, when it comes to its user interface, Blender still doesn’t feel quite properly integrated within the macOS environment. This GSoC proposal aims to change this, with the goal of making Blender feel closer to a fully native macOS application.
Benefits
This proposal plans to improve the Blender macOS user experience by incorporating part of the Blender interface into the macOS interface. Effectively making it closer to the macOS Human Interface Guidelines, and providing macOS Blender users with a familiar experience, more tightly integrated into their operating system.
To achieve this goal, this proposal will focus on the improvements of two main UI elements: the macOS menu bar and title bar. While this proposal will focus on macOS implementation, a byproduct of it will be the creation of an unified interface for native menu bar items, which will then make it possible to implement such functionality on other OSes and Desktop Environments in the future.
You can find more details about the project and its deliverables in the project’s proposal.
In this thread, you will find the project’s weekly reports. Feel free to also share your thoughts and feedback in the project dedicated feedback thread.
So: Accepted project, but focus on client side decorations (CSD) / title bar:
Prototyping for title bar/ CSD
API design for controlling & drawing into title bar
If at the end we have good knowledge of how to implement custom title bars in Blender, that’s a great outcome. More is bonus.
Julian and Raul will mentor
Communication
Thomas: Development Coordinator
Public by default
Which chat channel to use? UI module? Separate channel? Check with Thomas
Weekly reports
Weekly sync up meetings
Process
As much as possible in main branch. Might be difficult bc of the nature of the project.
Expect regular commits, daily if possible. WIP changes allowed.
Single project PR, more PRs as useful/needed
It’s fine to work on other MacOS/UI improvements (e.g. refactoring Ghost Cocoa code). But focus shouldn’t derail too much.
Next Week(s) Planning
1st two weeks: Prototyping & API research
Focus on biggest uncertainties (e.g. adding space to drag)
Potential Issues
Extending the topbar into window decorations
How to handle window buttons? Different position/size on different platform etc
How does macOS know we clicked on empty space for dragging the window? Is the event tagged as consumed? Can you add dragging hotspots? Something to investigate.
Window controls should remain interactive if Blender is frozen, avoid handling in own UI/window-manager code
Design: Windows without topbar? Preferences etc
Design: Where to place the file path, Blender version etc?
Preliminary progress on draggable areas using an overlay that catches window drag events
Research
Cocoa / Objective-C documentation
Existing macOS inline titlebar in other softwares for design and implementation references
Code-wise, I wasn’t that productive this week as I ended up having to finish some personal work which should still take me up to around Tuesday, after which I’ll be more available to work on the project.
Next goals:
Proper handling of the topbar layout area rectangle (enabling proper padding, traffic light alignment, and more)
Differentiating between main blender windows and child/auxiliary windows to properly apply decorations
Starting to draft a proper macOS inline titlebar design, research and answer practical design questions (Filename placement, bar state during loading, etc…)
Globally quite an unproductive week GSoC wise as I was busy with a personal project I couldn’t postpone from Thursday to Monday afternoon. However, starting tomorrow, I’ll have my entire week free to work on the project and catch back up.
Still, this week, I worked on non-inline titlebar macOS decoration for non-main windows (Preferences, popped-out editors, Render View, etc…) which I plan to release this week as a standalone PR along with a separate refactor PR of the Cocoa/Objective-C GHOST macOS layer.
Following that idea, I decided with my two mentors to postpone prototyping on the main inline window decoration task for now to focus on landing usable and finished macOS UI/UX deliverables for users to play with. And will thus next focus on fixing the macOS window sizing and placement bugs, and possibly work on globally improving window restoration, as was discussed in this PR.
Once that’s done, I will split my time between continuing work on inline window decorations (see previous reports), and working on other macOS UX deliverables, such as iCloud integration, improved text cursor behavior, better system interactions, maybe better app packaging using Universal Binaries, and if I have some additional time, some global UI papercuts improvements.
We do have a TODO about it, but it is aimed to be done as part of Steam packaging. Using universal binary for all other places has a downside of heavily increased download size. Which is especially unideal since the x86 macOS platforms seems to be on their way to be phased out.
I wouldn’t really prioritize this for the GSoC project.
Right yeah, I see what you mean, just to see, I did some quick tests to see what a universal binary build would cost us in terms of size. Here are the results on the latest commit from main (56fdfe5) using the default CMake Release config, with the universal binary created using lipo.
Binary
Size
arm64
156,4 MB
x86_64
170,9 MB
Universal
327,3 MB
This does make for an increase in binary size of 109%, effectively doubling it, as the two binaries are really just appended to each others, however, when we look at the total macOS app bundle size, we get:
.app Bundle
Size
arm64
812 MB
x86_64
866,8 MB
Universal
982,9 MB
Which gives us an increase of 21% from arm64 to Universal, which is still consequential, but has already way less of an impact on the total download size.
For me, the eventual rational for shipping Blender as an universal binary, like other FOSS softwares do, such as Godot, is less about guaranteeing multi-arch support, and more about making sure users don’t accidentally run Blender through Rosetta, thus lowering their performances, a problem I already ran into myself in the past after copying Blender builds between macs, and keeping old DMGs around. Especially since there’s no way of realizing that you’re actually running Blender through emulation, unless you inspect the application or use an external indicator like Silicon Info.
This situation might even actually degrade with time, as Intel Macs become more rare, Blender will still need to keep shipping x86_64 builds for as long as they’re officially supported, as such, the number of users potentially using the wrong builds and lowering their performances might actually increase with time. Although this can of course also be solved through clear Download guidelines, or eventually some sort of splash screen indicator that Blender is currently being run under Rosetta, using an Universal Binary might be a simpler solution.
On the technical side of things, CMake does most of the heavy lifting for us, to build an x86_64 binary on arm64, just setting the CMAKE_OSX_ARCHITECTURE=x86_64 build flag is enough, along with manually enabling the lib/macos_x64 submodule. Ideally, we’d want CMake to be able to perform the lipo concatenation itself using CMAKE_OSX_ARCHITECTURES=arm64;x86_64, which currently fails due to the library directory search not expecting multiple architectures, but I might dig a bit more into it later to see if that’s easily fixable.
As you said, this is certainly not an obvious tradeoff, and would certainly require more discussion with the Platform module, but all in all, it might be worth it as a way to globally make things simpler, guaranteeing good performances and simplifying release builds creation and distribution, especially considering that the end download size increase is not that consequential.
If you want to continue this discussion, feel free to either reply here or ping me on blender.chat if you prefer to not pollute this thread too much, I can also create another devtalk topic if you’d think that’s more appropriate.
Ah… Good point you’re right, indeed I didn’t factor in the rest of the executable libs that needs to be turned into universal binaries, as I just based myself off the existing arm64 bundle to quickly throw something together (which of course only worked on my machine, doing the same thing using the x86_64 bundle would cause a crash due to missing libs).
I took a stab at trying to properly generate Universal App Bundles for macOS. For this to work, all used libraries need to be concatenated using lipo just like the Blender executable itself. As a quick experiment, I wrote a simple Python script that creates the universal libraries by merging the lib/macos_arm64 and lib/macos_x64 directories into a lib/macos_universal directory, using lipo if the file is an executable or static/dynamic lib, recreating relative symlinks, and simply copying every other files, which I then fed into CMake.
As the resulting bundle basically doubles the download size, the whole idea of using these for Blender releases kinds of fall through. Still, I’ll probably turn the script and slight CMake modifications I made into a proof of concept PR for anyone who wants to experiment with this or want to be able to build a Universal Binary version of Blender for themselves (and eventually also as a base solution for the TODO PR@sergey mentioned). As a future side-task, I might also experiment with displaying a splash screen warning if Blender is being run through Rosetta to still address the problem I talked about above.
The way Steam delivery currently works is that it downloads builds from buildbot, repackages, and pushes them to steam. It does not do compilation. If we can have a script to which you can give two builds of Blender (x86 and arm64) that’d make it easy to attach it to the current pipeline. Do you think it is possible (it actually sounds you have similar script already)?
Ah right I see, yeah for sure that should be possible. The script I made merges two pre-compiled library directories together so that they can be used to compile a Universal Binary, but I should be able to adapt it for it to take two x86_64 and arm64 Blender app bundles instead for this to be done post-compilation.
It even somewhat simplifies things as we don’t have to deal with library symlinks and merging static libraries together to please the compiler, just merging the Blender executable and embedded dynamic libraries inside the bundle should be enough. I’ll modify the script in that sense, would you like me to drop it here once it’s done or do you prefer me opening a PR somewhere?
I think you can create a PR against the blender-devops. Maybe place it under blender-devops/buildbot/worker/blender. I forgot how exactly the Steam re-packaging work, but it seems it already does unpacking of DMG. Perhaps this could simplify some work for you. The details of that part are in the blender-devops/buildbot/worker/deploy/steam.py. Ideally we download both DMGs and call a function from your script.
Unless you want to dig into more details of this devops pipeline, you can provide script which you think will lets us do an universal build, and then we do the devops pipeline side of the changes.
See the Pull Request for other screenshots, videos and details
Objective-C Refactor Research
The original plan for this week was to publish an initial GHOST Cocoa/Objective-C Refactor PR to serve as a clean base for the above macOS client-side decorations PR. However, as I started to work on the refactor, the scope of the task grew beyond what I anticipated for a simple PR, as the GHOST and overall Blender Objective-C code is largely outdated, not only in terms of style, but also in terms of API usage and memory management (we currently use the “old” Obj-C MRR memory management style, but newer code was written with the expectation of having automatic reference counting enabled, causing leaks among other major inconsistencies).
I thus decided to postpone this refactor, in favor of publishing the above PR, as to then be able to focus on it in one block, going beyond simple stylistic changes (see Next Goals below) with the goal of providing Blender with an updated, modern and stable Objective-C software layer.
Additional Researches on macOS Universal Binary builds (see previous messages in this thread)
Next Goals:
Objective-C/Cocoa Refactor - In multiple steps/PRs:
1st: Stylistic Refactor - Using @autoreleasepool instead of NSAutoReleasePool, includes/imports and comment cleaning, enforcing dot notation for setting properties (using foo.thing = c instead of [foo setThing:c]), etc…
2nd: Memory Management - Enabling and switching to Automatic Reference Counting (ARC) and rewriting functions in that sense, fixing leaks and over-retains.
I ended up coming down with a pretty bad cold this week, which knocked me out for most of it. As a result, my work was mainly concentrated over the last few days. Here’s what I produced in this period:
This Week:
Fixed a bug where floating window title would not properly update on editor change (Pull Request)
Implemented a Splash Screen notice to warn against reduced performance if Blender is ran through Rosetta on macOS (Pull Request)
Progress on the first phase of the Objective-C Refactor (see previous week’s goals), with a PR coming in the next few days
Experimented with using AppKit’s NSColorSampler as an alternative eyedropper for picking color outside of the macOS Blender window, triggered when shift-clicking the eyedropper icon
Progress this last week has been quite steady, mainly focusing on the Objective-C refactor.
This Week:
Continued the work on the first phase of the Objective-C refactor, the scope of which has broaden to now also cover the refactoring of macOS specific delegates and subclasses of AppKit objects
Continued experiments on an improved Color Picker layout, with a WIP PR coming soon
Finish and publish the first phase of the Objective-C Refactor
Continue on with the rest of previous goals (rest of the Objective-C refactor, Universal Binary Steam package delivery, Inline Titlebar Decorations, etc…). See the Week 5 Goals for more details
Not that much overall progress this week, while I had originally hoped to release my work towards the end of the week, I ended up coming down with food poisoning which knocked me out for the better part of it.
This Week:
Overall progress on main tasks (Objective-C Refactor and other experiments)
Participated in Thursday’s UI Module Meeting
Showcased the project and discussed its direction
Got feedback on PRs and discussed their UI design
Discussed future macOS/UI related goals and targets (Cross-platform CSD, macOS image copy-pasting support, etc…)
Hoping that this sickness won’t last too long, my next goal is going to catch up on and release my current tasks, clear the accumulated backlog, and move on to new deliverables.
Overall a much more productive week, here’s what has been accomplished in this period:
This Week:
Objective-C Refactor
Finished the main Cocoa Refactor, overhauling style, memory management, AppKit subclasses, and more, making for a more solid and maintainable base for further macOS improvements. Final diff of +1594, -1671 changes
Ported the BLI_delete_soft function from Obj-C Runtime code to proper Objective-C
Objective-C allocations and release pool profiling, leaks corrected in the refactor
Experimented with new macOS specific deliverables taking advantages of the Cocoa Refactor (see Next Goals)
Next Goals:
macOS Image Copy/Pasting Support
macOS Titlebar filename and save indicator text improvements
Add iCloud in the File Explorer sidebar and port the underlying macOS filesystem code to modern Objective-C
More Objective-C Refactors (Carbon Deprecation, Metal code, etc…)
As a small bonus, macOS builds for the Colored macOS Titlebar PR are available here. Feel free to test it and share your feedback in this thread if you’re interested.
Apologies for the late report, ended up being quite busy towards the end of last week, which led me to essentially concentrate on polishing existing features and bug-fixing. However, the great news is that starting today, I’m officially on vacation, which will let me entirely focus on the project in the coming days, working on new deliverables and larger tasks.
This Week:
Participated in Thursday’s UI Module Meeting
Got feedback on and discussed project deliverables/PRs
Showcased and discussed new Color related ideas (Color Picker layout rework, Color Datablock drag and drop, Improved Color Nodes)
Discussed future macOS integrations (Dark/Light Theme Auto-Switching, Finder Integration in the File browser, and more)
Finishing up the design of the new WM/GHOST Client-Side Decorations API deliverable as part of the Colored Titlebar PR.
Expandable flag-based API, featuring the possibility of applying multiple decorations style flags on a per-window basis
Provides Blender with a simple platform-independent and future-proof decoration API, allowing to create dynamic decorations using the current theme or window state
API overview/writeup coming soon once the design will be completely final
macOS Image Copy/Pasting Support:
Demo - PR Coming Soon, some tweaks are still needed to properly cover all image source and destination types.
Next week:
As the very last week of GSoC (starting August 19th) will overlap with me starting a new (Blender related \o/) job, I’ll be less available in this final period. Next week will thus be focused on finishing and releasing in progress deliverables and refactors to start wrapping up the project.