macOS: Colored Titlebar and WM Client-Side Decorations API - GSoC 2024 #123982
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Code Documentation
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
10 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#123982
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "Brainzman/blender:gsoc-simple-titlebar-csd"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
As part of the GSoC 2024 project Improvements to the Blender macOS User Interface Experience, this pull request implements custom colored titlebar window decorations on macOS, following the Blender theme colors, as well as a basic GHOST API for enabling and implementing custom client-side window decorations on other systems.
Screenshots
Blender Dark Theme
Blender Light Theme
Nordic Gold Theme (link)
Video Demo with different windows/themes
Featured themes can be found on the Blender Extensions Platform
Titlebar blending with Editor header
Technical Notes
Titlebar Text Color
The original goal was to let the Blender themes not only dictate the macOS titlebar background color, but also its foreground/text color. However, modifying the titlebar text color on macOS proved to be tricky and impractical, as it either required the use of Objective-C reflection / private APIs, or recreating an entirely new titlebar view from scratch, with both solutions proving themselves to be relatively unreliable, not future-proof, and prone to breaking on macOS updates.
Thus, the chosen solution was to instead stick to the default macOS titlebar text color, and set it to either use its dark or light appearance variant depending on the current theme. This solution better guarantees that we stick to the overall macOS style and guidelines, and is also used by other GUI frameworks and softwares such as Qt or IntelliJ IDEs. Since Blender does not tag its themes as being light or dark, the titlebar background color is used to determine which variant to apply, using its HSV value component.
For implementation on other systems, the GHOST
setTitlebarCSDColors
API function still expose both the titlebar background and text color as arguments, with the macOS implementation only using the background color.Slight titlebar flash on theme change
Due to small timing differences in drawing updates, the titlebar may sometimes briefly flash on theme changes due to it updating a few frames after the window content view, as can be sometimes seen in the first demo video. While I have been able to reduce the issue by making the titlebar update more consistently with the main content view, I haven't looked into achieving perfect synchronization yet, which would require lower-level work that's out of scope for this PR, and would be better part of a separate project to allow proper redraw synchronization on theme change.
New WM Decoration API Overview
The main idea behind this new API is for it to be as light and simple as possible, and for decorations to be tied to windows, not global state. Multiple decoration flags can be set on each windows (via
WM_window_decoration_set_style
), which can also depend on the current theme (seewm_window_decoration_parse_theme
, called byWM_decoration_apply
).To keep this API as platform independent as possible, decoration style flags and settings are stored in the base
GHOST_Window
class. This means that to implement this decoration on another backend, the only thing that needs to be done is to override theapplyDecoration()
function on the target backend, see the existing macOS implementation inGHOST_WindowCocoa.mm
.WIP: macOS Colored Titlebar Client-Side Decorations - GSoC 2024to macOS: Colored Titlebar Client-Side Decorations - GSoC 2024Very nice!
Nice indeed! Now I know what GSoC stands for: Great Summer of Color 🌈
I'm learning about the Cocoa side of GHOST things, so I took the liberty to take a look at your code. I marked a few tiny things I spotted.
@ -596,2 +596,4 @@
extern GHOST_TSuccess GHOST_SetPath(GHOST_WindowHandle windowhandle, const char *filepath);
/**
* Enable or disable custom client-side window decorations
Silly nitpick, but the style guide tells us to end comments with a full stop.
Applies here and several other places.
@ -598,0 +599,4 @@
* Enable or disable custom client-side window decorations
* \param useCSD: Whether to use custom client-side window decorations
*/
extern void GHOST_SetUseCSD(GHOST_WindowHandle windowhandle, bool useCSD);
The abbreviation
CSD
is a bit cryptic, I think. In the context of this PR I understand it, but when I would come acrossWM_window_set_use_csd(win, true)
in the wild, I wouldn't know what it meant.Perhaps something less technical, more functional, like
CustomDecorations
?And a question: is it meant that users have a choice to use custom decorations, e.g. in the Preferences? As far as I can see,
m_useCSD
is now always set totrue
for all windows Blender is creating. So it could be omitted. But perhaps that's not true in the broader scope of plans.@ -598,0 +607,4 @@
* \param tbTitleTextCol: Titlebar title text color
*/
extern void GHOST_SetTitlebarCSDColors(GHOST_WindowHandle windowhandle,
const float tbBackgroundCol[4],
Second nitpick: better full variable names like
backgroundColor
thantbBackgroundCol
. The 'title bar' part is implied by the function.@ -312,6 +325,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
bool m_immediateDraw;
bool m_debug_context; // for debug messages during context setup
bool m_is_dialog;
bool m_use_decoration;
Is this one used?
@ -2740,0 +2757,4 @@
/**
* Return whether the window should contain global areas (topbar/statusbar)
*/
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
Third nitpick: you can use
const
here, soconst bScreen *screen =
.@SietseB Thanks for the feedback! I addressed them in the commits above. Regarding the CSD abbreviation, while it does look a bit cryptic without context, it's important to highlight that this function refers to Client-Side Decorations. To which CSD is the common acronym (see Wikipedia). This also importantly underlines that we're interacting with the OS Window Manager, drawing outside our window bounds.
While I would prefer to be as clear as possible,
GHOST_SetUseClientSideDecorations
andGHOST_SetTitlebarClientSideDecorationsColor
feel too verbose, and dropping theClientSide
part might be more confusing, as I feel like that would implicitly refer to in-window decorations. In any case, the Doxygen header comments do provide descriptions of the functions, but if you feel like that's not enough, I can search for another solution/clearer and shorter names.Regarding the
m_useCSD
flag, this is mainly to give the Window Manager code control over CSDs, which could serve to conditionally disable them in the future, or only enable them on specific windows on certain platforms. For example the initial implementation of this PR used to disable them for main windows on macOS, which is way easier to do directly from the WM code, than to try to make checks from the GHOST code.So
m_useCSD
is indeed part of a bigger/future plan, I already thought so. So that's fine as it is 👍And I fully understand your considerations around the CSD naming. Writing it in full, well, yeah – your tea will be cold before you finish reading 😄 Perhaps adding a little comment in
wm_windows.cc
to clarify? To keep that file readable without hovering or clicking to definitions in header files.Just a tiny idea, I leave it up to you.
You're right that a small comment in
wm_windows.cc
won't hurt, I also specified the CSD acronym in the description of GHOST functions to make it a bit clearer. Thanks for the overall feedback! :)@blender-bot package
Package build started. Download here when ready.
@blender-bot package
Package build started. Download here when ready.
@ -596,2 +596,4 @@
extern GHOST_TSuccess GHOST_SetPath(GHOST_WindowHandle windowhandle, const char *filepath);
/**
* Enable or disable custom client-side window decorations (CSD).
Not a big fan of naming this "CSD". I generally prefer avoiding abbreviations since they can be ambiguous (can mean different things depending on context). I also find that names can often be avoided and the intention/behavior can be described more directly, which makes the API more user friendly.
Also this isn't really connected yet to full client side decorations as we do them on Linux with Wayland. So using "CSD" here can be misleading too.
I'd propose to name this
GHOST_SetWindowDecorationStyle()
and let it take an enum like:I find this expresses things better.
@ -518,0 +517,4 @@
const char area_spacetype = area ? area->spacetype : 0;
/* Set client-side window decoration titlebar colors. */
if (at->regionid == RGN_TYPE_WINDOW) {
Don't think this function is the right place for this logic. It is run for every region for every redraw. I think the
NC_WINDOW
inED_screen_do_listen
could handle this. ANC_WINDOW
notifier is sent on every theme change. I'd also put this into a separate function, so it's clear that this is all doing a specific task.@ -2730,6 +2749,18 @@ bool WM_window_is_maximized(const wmWindow *win)
return win->windowstate == GHOST_kWindowStateMaximized;
}
bool WM_window_has_global_areas(const wmWindow *win)
The name suggests that this checks if the window has in fact global areas. What it actually checks if it should have them. Suggest
WM_window_should_have_global_areas()
.ENUM_OPERATORS
max enum value for the CSD WM Capability flag 4c7a447289Window
prefix from GHOST Decoration API for simplification 164e1dcb9da1fc6fb18c
to7ce368fe4b
styleFlags
035cad0d86GHOST_DecorationSettings
struct f78fcb9135decoration_parse_theme
function static f2ec1a0309WM_window_decoration_apply
argument 939e5a06edAfter much refactoring and refinements, this Pull Request now features a new WM Client-Side Decorations API, a deliverable of this GSoC project.
WM Decoration API Overview
The main idea behind this API is for it to be as light and simple as possible, and for decorations to be tied to windows, not global state. Multiple decoration flags can be set on each windows (via
WM_window_decoration_set_style
), which can also depend on the current theme (seewm_window_decoration_parse_theme
, called byWM_decoration_apply
).To keep this API as platform independent as possible, decoration style flags and settings are stored in the base
GHOST_Window
class. This means that to implement this decoration on another backend, the only thing that needs to be done is to override theapplyDecoration()
function on the target backend, see the existing macOS implementation inGHOST_WindowCocoa.mm
(cc @Harley if you're interested)Other refactors / improvements since review include:
This works great on Windows 11 (prior versions can't set an exact titlebar color).
I just removed GHOST_kCapabilityClientSideWindowDecorations from that getCapabilities list, then made an applyDecoration like this:
Like on Mac I wouldn't want to set the caption text color because the OS does a good job of setting a contrasting color and dims it when the window is not active.
The colors match perfectly.
I especially like how it looks for the Preferences window.
Oooh this looks amazing! Thank you so much for taking the time to implement it! I'm so glad you were able to port this to Windows with this little code
macOS: Colored Titlebar Client-Side Decorations - GSoC 2024to macOS: Colored Titlebar and WM Client-Side Decorations API - GSoC 2024@JulianEisel Hey there, I very slightly tweaked this PR to be consistent with the now merged in Objective-C refactor and updated its title, it should all be ready for final review now.
@blender-bot package
Only blender organization members with write access can start builds. See documentation for details.
Nice work! Could organization members review and merge it into the main branch?
@hologerry Julian is busy finishng up Brush Assets for 4.3. This patch is not a target for 4.3, thus it has to wait.
But the community at large is welcome to help with the code review (and testing). I will kick a new build.
@blender-bot package macos
Package build started. Download here when ready.
@dfelinto Thanks!
@blender-bot package macos
Package build started. Download here when ready.
Checkout
From your project repository, check out a new branch and test the changes.