diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 535711bab22..eb79788a069 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -593,6 +593,31 @@ extern char *GHOST_GetTitle(GHOST_WindowHandle windowhandle); */ extern GHOST_TSuccess GHOST_SetPath(GHOST_WindowHandle windowhandle, const char *filepath); +/** + * Return the current window decoration style flags. + */ +extern GHOST_TWindowDecorationStyleFlags GHOST_GetWindowDecorationStyleFlags( + GHOST_WindowHandle windowhandle); + +/** + * Set the window decoration style flags. + * \param styleFlags: Window decoration style flags. + */ +extern void GHOST_SetWindowDecorationStyleFlags(GHOST_WindowHandle windowhandle, + GHOST_TWindowDecorationStyleFlags styleFlags); + +/** + * Set the window decoration style settings. + * \param decorationSettings: Window decoration style settings. + */ +extern void GHOST_SetWindowDecorationStyleSettings( + GHOST_WindowHandle windowhandle, GHOST_WindowDecorationStyleSettings decorationSettings); + +/** + * Apply the window decoration style using the current flags and settings. + */ +extern GHOST_TSuccess GHOST_ApplyWindowDecorationStyle(GHOST_WindowHandle windowhandle); + /** * Returns the window rectangle dimensions. * These are screen coordinates. diff --git a/intern/ghost/GHOST_IWindow.hh b/intern/ghost/GHOST_IWindow.hh index c48137f6d77..4c38a9b83bc 100644 --- a/intern/ghost/GHOST_IWindow.hh +++ b/intern/ghost/GHOST_IWindow.hh @@ -87,6 +87,29 @@ class GHOST_IWindow { */ virtual GHOST_TSuccess setPath(const char *filepath) = 0; + /** + * Return the current window decoration style flags. + */ + virtual GHOST_TWindowDecorationStyleFlags getWindowDecorationStyleFlags() = 0; + + /** + * Set the window decoration style flags. + * \param styleFlags: Window decoration style flags. + */ + virtual void setWindowDecorationStyleFlags(GHOST_TWindowDecorationStyleFlags styleFlags) = 0; + + /** + * Set the window decoration style settings. + * \param decorationSettings: Window decoration style settings. + */ + virtual void setWindowDecorationStyleSettings( + GHOST_WindowDecorationStyleSettings decorationSettings) = 0; + + /** + * Apply the window decoration style using the current flags and settings. + */ + virtual GHOST_TSuccess applyWindowDecorationStyle() = 0; + /** * Returns the window rectangle dimensions. * These are screen coordinates. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index e89256b3eef..fcf5f2ab221 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -119,6 +119,10 @@ typedef enum { * Support detecting the physical trackpad direction. */ GHOST_kCapabilityTrackpadPhysicalDirection = (1 << 7), + /** + * Support for window decoration styles. + */ + GHOST_kCapabilityWindowDecorationStyles = (1 << 8), } GHOST_TCapabilityFlag; /** @@ -129,7 +133,8 @@ typedef enum { (GHOST_kCapabilityCursorWarp | GHOST_kCapabilityWindowPosition | \ GHOST_kCapabilityPrimaryClipboard | GHOST_kCapabilityGPUReadFrontBuffer | \ GHOST_kCapabilityClipboardImages | GHOST_kCapabilityDesktopSample | \ - GHOST_kCapabilityInputIME | GHOST_kCapabilityTrackpadPhysicalDirection) + GHOST_kCapabilityInputIME | GHOST_kCapabilityTrackpadPhysicalDirection | \ + GHOST_kCapabilityWindowDecorationStyles) /* Xtilt and Ytilt represent how much the pen is tilted away from * vertically upright in either the X or Y direction, with X and Y the @@ -694,6 +699,11 @@ typedef enum { /* Can be extended as needed. */ } GHOST_TUserSpecialDirTypes; +typedef enum { + GHOST_kDecorationNone = 0, + GHOST_kDecorationColoredTitleBar = (1 << 0), +} GHOST_TWindowDecorationStyleFlags; + typedef struct { /** Number of pixels on a line. */ uint32_t xPixels; @@ -720,6 +730,11 @@ typedef struct { GHOST_GPUDevice preferred_device; } GHOST_GPUSettings; +typedef struct { + float colored_titlebar_bg_color[3]; + float colored_titlebar_fg_color[3]; +} GHOST_WindowDecorationStyleSettings; + #ifdef WITH_VULKAN_BACKEND typedef struct { /** Image handle to the image that will be presented to the user. */ diff --git a/intern/ghost/intern/GHOST_C-api.cc b/intern/ghost/intern/GHOST_C-api.cc index 221b60973cc..535c57bebc9 100644 --- a/intern/ghost/intern/GHOST_C-api.cc +++ b/intern/ghost/intern/GHOST_C-api.cc @@ -606,6 +606,33 @@ GHOST_TSuccess GHOST_SetPath(GHOST_WindowHandle windowhandle, const char *filepa return window->setPath(filepath); } +GHOST_TWindowDecorationStyleFlags GHOST_GetWindowDecorationStyleFlags( + GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + return window->getWindowDecorationStyleFlags(); +} + +void GHOST_SetWindowDecorationStyleFlags(GHOST_WindowHandle windowhandle, + GHOST_TWindowDecorationStyleFlags styleFlags) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + window->setWindowDecorationStyleFlags(styleFlags); +} + +void GHOST_SetWindowDecorationStyleSettings(GHOST_WindowHandle windowhandle, + GHOST_WindowDecorationStyleSettings decorationSettings) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + window->setWindowDecorationStyleSettings(decorationSettings); +} + +GHOST_TSuccess GHOST_ApplyWindowDecorationStyle(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + return window->applyWindowDecorationStyle(); +} + GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle) { const GHOST_IWindow *window = (const GHOST_IWindow *)windowhandle; diff --git a/intern/ghost/intern/GHOST_SystemHeadless.hh b/intern/ghost/intern/GHOST_SystemHeadless.hh index bdd177ec084..a1fb27ec612 100644 --- a/intern/ghost/intern/GHOST_SystemHeadless.hh +++ b/intern/ghost/intern/GHOST_SystemHeadless.hh @@ -54,7 +54,8 @@ class GHOST_SystemHeadless : public GHOST_System { ~(GHOST_kCapabilityWindowPosition | GHOST_kCapabilityCursorWarp | GHOST_kCapabilityPrimaryClipboard | GHOST_kCapabilityDesktopSample | - GHOST_kCapabilityClipboardImages | GHOST_kCapabilityInputIME)); + GHOST_kCapabilityClipboardImages | GHOST_kCapabilityInputIME | + GHOST_kCapabilityWindowDecorationStyles)); } char *getClipboard(bool /*selection*/) const override { diff --git a/intern/ghost/intern/GHOST_SystemSDL.cc b/intern/ghost/intern/GHOST_SystemSDL.cc index 6020b6a0ecf..18f1638d0b3 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cc +++ b/intern/ghost/intern/GHOST_SystemSDL.cc @@ -791,7 +791,9 @@ GHOST_TCapabilityFlag GHOST_SystemSDL::getCapabilities() const /* This SDL back-end has not yet implemented image copy/paste. */ GHOST_kCapabilityClipboardImages | /* No support yet for IME input methods. */ - GHOST_kCapabilityInputIME)); + GHOST_kCapabilityInputIME | + /* No support for window decoration styles. */ + GHOST_kCapabilityWindowDecorationStyles)); } char *GHOST_SystemSDL::getClipboard(bool /*selection*/) const diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index 228c48803f8..60389feafc4 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -8730,6 +8730,10 @@ GHOST_TCapabilityFlag GHOST_SystemWayland::getCapabilities() const GHOST_kCapabilityGPUReadFrontBuffer | /* This WAYLAND back-end has not yet implemented desktop color sample. */ GHOST_kCapabilityDesktopSample | + /* This WAYLAND back-end doesn't have support for window decoration styles. + * In all likelihood, this back-end will eventually need to support client-side + * decorations, see #113795. */ + GHOST_kCapabilityWindowDecorationStyles | /* This flag will eventually be removed. */ ((has_wl_trackpad_physical_direction == 1) ? 0 : diff --git a/intern/ghost/intern/GHOST_SystemWin32.cc b/intern/ghost/intern/GHOST_SystemWin32.cc index 0fefead3019..d9d43376e23 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cc +++ b/intern/ghost/intern/GHOST_SystemWin32.cc @@ -586,7 +586,10 @@ GHOST_TCapabilityFlag GHOST_SystemWin32::getCapabilities() const return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL & ~( /* WIN32 has no support for a primary selection clipboard. */ - GHOST_kCapabilityPrimaryClipboard)); + GHOST_kCapabilityPrimaryClipboard | + /* This WIN32 backend has not yet implemented support for window + * decoration styles. */ + GHOST_kCapabilityWindowDecorationStyles)); } GHOST_TSuccess GHOST_SystemWin32::init() diff --git a/intern/ghost/intern/GHOST_SystemX11.cc b/intern/ghost/intern/GHOST_SystemX11.cc index 740b47170c6..94d744674ad 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cc +++ b/intern/ghost/intern/GHOST_SystemX11.cc @@ -1817,7 +1817,9 @@ GHOST_TCapabilityFlag GHOST_SystemX11::getCapabilities() const /* No support yet for image copy/paste. */ GHOST_kCapabilityClipboardImages | /* No support yet for IME input methods. */ - GHOST_kCapabilityInputIME)); + GHOST_kCapabilityInputIME | + /* No support for window decoration styles. */ + GHOST_kCapabilityWindowDecorationStyles)); } void GHOST_SystemX11::addDirtyWindow(GHOST_WindowX11 *bad_wind) diff --git a/intern/ghost/intern/GHOST_Window.cc b/intern/ghost/intern/GHOST_Window.cc index 1c227c18bd9..45e7607d735 100644 --- a/intern/ghost/intern/GHOST_Window.cc +++ b/intern/ghost/intern/GHOST_Window.cc @@ -32,6 +32,8 @@ GHOST_Window::GHOST_Window(uint32_t width, m_progressBarVisible(false), m_canAcceptDragOperation(false), m_isUnsavedChanges(false), + m_windowDecorationStyleFlags(GHOST_kDecorationNone), + m_windowDecorationStyleSettings(), m_wantStereoVisual(wantStereoVisual), m_nativePixelSize(1.0f), m_context(new GHOST_ContextNone(false)) @@ -55,6 +57,22 @@ void *GHOST_Window::getOSWindow() const return nullptr; } +GHOST_TWindowDecorationStyleFlags GHOST_Window::getWindowDecorationStyleFlags() +{ + return m_windowDecorationStyleFlags; +} + +void GHOST_Window::setWindowDecorationStyleFlags(GHOST_TWindowDecorationStyleFlags styleFlags) +{ + m_windowDecorationStyleFlags = styleFlags; +} + +void GHOST_Window::setWindowDecorationStyleSettings( + GHOST_WindowDecorationStyleSettings decorationSettings) +{ + m_windowDecorationStyleSettings = decorationSettings; +} + GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType type) { if (type != m_drawingContextType) { diff --git a/intern/ghost/intern/GHOST_Window.hh b/intern/ghost/intern/GHOST_Window.hh index 3c4ba9bbfee..7c565864fca 100644 --- a/intern/ghost/intern/GHOST_Window.hh +++ b/intern/ghost/intern/GHOST_Window.hh @@ -89,6 +89,33 @@ class GHOST_Window : public GHOST_IWindow { return GHOST_kFailure; } + /** + * Return the current window decoration style flags. + */ + virtual GHOST_TWindowDecorationStyleFlags getWindowDecorationStyleFlags() override; + + /** + * Set the window decoration style flags. + * \param styleFlags: Window decoration style flags. + */ + virtual void setWindowDecorationStyleFlags( + GHOST_TWindowDecorationStyleFlags styleFlags) override; + + /** + * Set the window decoration style settings. + * \param decorationSettings: Window decoration style settings. + */ + virtual void setWindowDecorationStyleSettings( + GHOST_WindowDecorationStyleSettings decorationSettings) override; + + /** + * Apply the window decoration style using the current flags and settings. + */ + virtual GHOST_TSuccess applyWindowDecorationStyle() override + { + return GHOST_kSuccess; + } + /** * Returns the current cursor shape. * \return The current cursor shape. @@ -410,6 +437,10 @@ class GHOST_Window : public GHOST_IWindow { /** Stores whether this is a full screen window. */ bool m_fullScreen; + /** Window Decoration Styles. */ + GHOST_TWindowDecorationStyleFlags m_windowDecorationStyleFlags; + GHOST_WindowDecorationStyleSettings m_windowDecorationStyleSettings; + /** Whether to attempt to initialize a context with a stereo frame-buffer. */ bool m_wantStereoVisual; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.hh b/intern/ghost/intern/GHOST_WindowCocoa.hh index 7c20f20e1e0..a12b1ec8464 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.hh +++ b/intern/ghost/intern/GHOST_WindowCocoa.hh @@ -93,6 +93,11 @@ class GHOST_WindowCocoa : public GHOST_Window { */ GHOST_TSuccess setPath(const char *filepath) override; + /** + * Apply the window decoration style using the current flags and settings. + */ + GHOST_TSuccess applyWindowDecorationStyle() override; + /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 48b61348c75..d5f3f582104 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -565,6 +565,38 @@ GHOST_TSuccess GHOST_WindowCocoa::setPath(const char *filepath) return GHOST_kSuccess; } +GHOST_TSuccess GHOST_WindowCocoa::applyWindowDecorationStyle() +{ + @autoreleasepool { + if (m_windowDecorationStyleFlags & GHOST_kDecorationColoredTitleBar) { + const float *background_color = m_windowDecorationStyleSettings.colored_titlebar_bg_color; + + /* Titlebar background color. */ + m_window.backgroundColor = [NSColor colorWithRed:background_color[0] + green:background_color[1] + blue:background_color[2] + alpha:1.0]; + + /* Titlebar foreground color. + * Use the value component of the titlebar background's HSV representation to determine + * whether we should use the macOS dark or light titlebar text appearance. With values below + * 0.5 considered as dark themes, and values above 0.5 considered as light themes. + */ + const float hsv_v = MAX(background_color[0], MAX(background_color[1], background_color[2])); + + const NSAppearanceName win_appearance = hsv_v > 0.5 ? NSAppearanceNameVibrantLight : + NSAppearanceNameVibrantDark; + + m_window.appearance = [NSAppearance appearanceNamed:win_appearance]; + m_window.titlebarAppearsTransparent = YES; + } + else { + m_window.titlebarAppearsTransparent = NO; + } + } + return GHOST_kSuccess; +} + void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid"); diff --git a/source/blender/editors/screen/area.cc b/source/blender/editors/screen/area.cc index 3abccf7c491..cf2ec6b1e28 100644 --- a/source/blender/editors/screen/area.cc +++ b/source/blender/editors/screen/area.cc @@ -2720,6 +2720,13 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi WM_window_title(CTX_wm_manager(C), CTX_wm_window(C)); } + /* If window decoration styles are supported, send a notification to re-apply them. */ + /* TODO: The `bl_animation_keyframing` test fails here if WM_capabilities_flags is called in + * background mode. Remove the !G.background check once the test has been fixed. */ + if (!G.background && WM_capabilities_flag() & WM_CAPABILITY_WINDOW_DECORATION_STYLES) { + WM_event_add_notifier(C, NC_WINDOW, nullptr); + } + /* also redraw when re-used */ ED_area_tag_redraw(area); } diff --git a/source/blender/editors/screen/screen_edit.cc b/source/blender/editors/screen/screen_edit.cc index 5a3323f5c3b..6e93317b487 100644 --- a/source/blender/editors/screen/screen_edit.cc +++ b/source/blender/editors/screen/screen_edit.cc @@ -660,10 +660,16 @@ void ED_screen_do_listen(bContext *C, const wmNotifier *note) } break; case NC_WINDOW: + if (WM_capabilities_flag() & WM_CAPABILITY_WINDOW_DECORATION_STYLES) { + WM_window_apply_decoration_style(win, screen); + } screen->do_draw = true; break; case NC_SCREEN: if (note->action == NA_EDITED) { + if (WM_capabilities_flag() & WM_CAPABILITY_WINDOW_DECORATION_STYLES) { + WM_window_apply_decoration_style(win, screen); + } screen->do_draw = screen->do_refresh = true; } break; @@ -1312,7 +1318,7 @@ void ED_screen_global_areas_refresh(wmWindow *win) { /* Don't create global area for child and temporary windows. */ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); - if ((win->parent != nullptr) || screen->temp) { + if (!WM_window_is_main_top_level(win)) { if (win->global_areas.areabase.first) { screen->do_refresh = true; BKE_screen_area_map_free(&win->global_areas); diff --git a/source/blender/windowmanager/WM_api.hh b/source/blender/windowmanager/WM_api.hh index 7d73e826826..e7280d0a7f7 100644 --- a/source/blender/windowmanager/WM_api.hh +++ b/source/blender/windowmanager/WM_api.hh @@ -185,10 +185,12 @@ enum eWM_CapabilitiesFlag { WM_CAPABILITY_INPUT_IME = (1 << 6), /** Trackpad physical scroll detection. */ WM_CAPABILITY_TRACKPAD_PHYSICAL_DIRECTION = (1 << 7), + /** Support for window decoration styles. */ + WM_CAPABILITY_WINDOW_DECORATION_STYLES = (1 << 8), /** The initial value, indicates the value needs to be set by inspecting GHOST. */ WM_CAPABILITY_INITIALIZED = (1u << 31), }; -ENUM_OPERATORS(eWM_CapabilitiesFlag, WM_CAPABILITY_TRACKPAD_PHYSICAL_DIRECTION) +ENUM_OPERATORS(eWM_CapabilitiesFlag, WM_CAPABILITY_WINDOW_DECORATION_STYLES) eWM_CapabilitiesFlag WM_capabilities_flag(); @@ -284,6 +286,7 @@ void WM_window_rect_calc(const wmWindow *win, rcti *r_rect); * \note Depends on #UI_SCALE_FAC. Should that be outdated, call #WM_window_set_dpi first. */ void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect); +bool WM_window_is_main_top_level(const wmWindow *win); bool WM_window_is_fullscreen(const wmWindow *win); bool WM_window_is_maximized(const wmWindow *win); @@ -374,6 +377,29 @@ void WM_window_title(wmWindowManager *wm, wmWindow *win, const char *title = nul bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check); +/* Window Decoration Styles. */ + +/* Flags for #WM_window_decoration_set_style(). + * NOTE: To be kept in sync with #GHOST_TWindowDecorationFlags. */ +enum eWM_WindowDecorationStyleFlag { + /** No decoration styling. */ + WM_WINDOW_DECORATION_STYLE_NONE = 0, + /** Colored Titlebar. */ + WM_WINDOW_DECORATION_STYLE_COLORED_TITLEBAR = (1 << 0), +}; +ENUM_OPERATORS(eWM_WindowDecorationStyleFlag, WM_WINDOW_DECORATION_STYLE_COLORED_TITLEBAR) + +/* Get/set window decoration style flags. */ +eWM_WindowDecorationStyleFlag WM_window_get_decoration_style_flags(const wmWindow *win); +void WM_window_set_decoration_style_flags(const wmWindow *win, + eWM_WindowDecorationStyleFlag style_flags); +/* Apply the window decoration style using the current style flags and by parsing style + * settings from the current Blender theme. + * The screen parameter is optional, and can be passed for enhanced theme parsing. + * NOTE: Avoid calling this function directly, prefer sending an NC_WINDOW WM notification instead. + */ +void WM_window_apply_decoration_style(const wmWindow *win, const bScreen *screen = nullptr); + /* `wm_files.cc`. */ void WM_file_autoexec_init(const char *filepath); diff --git a/source/blender/windowmanager/intern/wm_window.cc b/source/blender/windowmanager/intern/wm_window.cc index 4eea6101f31..110733a404c 100644 --- a/source/blender/windowmanager/intern/wm_window.cc +++ b/source/blender/windowmanager/intern/wm_window.cc @@ -598,6 +598,72 @@ void WM_window_set_dpi(const wmWindow *win) U.widget_unit = int(roundf(18.0f * U.scale_factor)) + (2 * pixelsize); } +eWM_WindowDecorationStyleFlag WM_window_get_decoration_style_flags(const wmWindow *win) +{ + const GHOST_TWindowDecorationStyleFlags ghost_style_flags = GHOST_GetWindowDecorationStyleFlags( + static_cast(win->ghostwin)); + + eWM_WindowDecorationStyleFlag wm_style_flags = WM_WINDOW_DECORATION_STYLE_NONE; + + if (ghost_style_flags & GHOST_kDecorationColoredTitleBar) { + wm_style_flags |= WM_WINDOW_DECORATION_STYLE_COLORED_TITLEBAR; + } + + return wm_style_flags; +} + +void WM_window_set_decoration_style_flags(const wmWindow *win, + eWM_WindowDecorationStyleFlag style_flags) +{ + unsigned int ghost_style_flags = GHOST_kDecorationNone; + + if (style_flags & WM_WINDOW_DECORATION_STYLE_COLORED_TITLEBAR) { + ghost_style_flags |= GHOST_kDecorationColoredTitleBar; + } + + GHOST_SetWindowDecorationStyleFlags( + static_cast(win->ghostwin), + static_cast(ghost_style_flags)); +} + +static void wm_window_decoration_style_set_from_theme(const wmWindow *win, const bScreen *screen) +{ + /* Set the decoration style settings from the current theme colors. + * NOTE: screen may be null. In which case, only the window is used as a theme provider. */ + GHOST_WindowDecorationStyleSettings decoration_settings = {}; + + /* Colored Titlebar Decoration. */ + /* For main windows, use the topbar color. */ + if (WM_window_is_main_top_level(win)) { + UI_SetTheme(SPACE_TOPBAR, RGN_TYPE_HEADER); + } + /* For single editor floating windows, use the editor header color. */ + else if (screen && BLI_listbase_is_single(&screen->areabase)) { + const ScrArea *main_area = static_cast(screen->areabase.first); + UI_SetTheme(main_area->spacetype, RGN_TYPE_HEADER); + } + /* For floating window with multiple editors/areas, use the default space color. */ + else { + UI_SetTheme(0, RGN_TYPE_WINDOW); + } + + float titlebar_bg_color[3], titlebar_fg_color[3]; + UI_GetThemeColor3fv(TH_BACK, titlebar_bg_color); + UI_GetThemeColor3fv(TH_BUTBACK_TEXT, titlebar_fg_color); + copy_v3_v3(decoration_settings.colored_titlebar_bg_color, titlebar_bg_color); + copy_v3_v3(decoration_settings.colored_titlebar_fg_color, titlebar_fg_color); + + GHOST_SetWindowDecorationStyleSettings(static_cast(win->ghostwin), + decoration_settings); +} + +void WM_window_apply_decoration_style(const wmWindow *win, const bScreen *screen) +{ + BLI_assert(WM_capabilities_flag() & WM_CAPABILITY_WINDOW_DECORATION_STYLES); + wm_window_decoration_style_set_from_theme(win, screen); + GHOST_ApplyWindowDecorationStyle(static_cast(win->ghostwin)); +} + /** * When windows are activated, simulate modifier press/release to match the current state of * held modifier keys, see #40317. @@ -857,6 +923,12 @@ static void wm_window_ghostwindow_ensure(wmWindowManager *wm, wmWindow *win, boo wm_window_ensure_eventstate(win); WM_window_set_dpi(win); + + if (WM_capabilities_flag() & WM_CAPABILITY_WINDOW_DECORATION_STYLES) { + /* Only decoration style we have for now. */ + WM_window_set_decoration_style_flags(win, WM_WINDOW_DECORATION_STYLE_COLORED_TITLEBAR); + WM_window_apply_decoration_style(win); + } } /* Add key-map handlers (1 handler for all keys in map!). */ @@ -2174,6 +2246,9 @@ eWM_CapabilitiesFlag WM_capabilities_flag() if (ghost_flag & GHOST_kCapabilityTrackpadPhysicalDirection) { flag |= WM_CAPABILITY_TRACKPAD_PHYSICAL_DIRECTION; } + if (ghost_flag & GHOST_kCapabilityWindowDecorationStyles) { + flag |= WM_CAPABILITY_WINDOW_DECORATION_STYLES; + } return flag; } @@ -2808,6 +2883,19 @@ bool WM_window_is_maximized(const wmWindow *win) return win->windowstate == GHOST_kWindowStateMaximized; } +bool WM_window_is_main_top_level(const wmWindow *win) +{ + /** + * Return whether the window is a main/top-level window. In which case it is expected to contain + * global areas (topbar/statusbar). + */ + const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + if ((win->parent != nullptr) || screen->temp) { + return false; + } + return true; +} + /** \} */ /* -------------------------------------------------------------------- */