0
0
mirror of https://github.com/vim/vim.git synced 2025-10-20 08:14:18 -04:00

patch 9.1.1834: MS-Windows: not possible to highlight the title bar

Problem:  MS-Windows: not possible to highlight the title bar
Solution: Make the title/caption bar configurable by introducing the
          'go-C' option value which allows to highlight it using the
          TitleBar and TitleBarNC highlighting groups (Mao-Yining).

Introduce titlebar color customization for Windows 11 GUI through
highlight groups and new 'guioptions' flag:

- Add 'C' flag to enable titlebar color customization (opt-in)
- New highlight groups: TitleBar (active) and TitleBarNC (inactive)
- Uses DWMWA_CAPTION_COLOR and DWMWA_TEXT_COLOR DWM attributes
- Dynamically loads dwmapi.dll for Windows 11 compatibility
- Defaults to system colors when set to NONE or feature disabled

closes: #18449

Signed-off-by: Mao-Yining <mao.yining@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Mao-Yining
2025-10-07 19:31:22 +00:00
committed by Christian Brabandt
parent f8b9251d8f
commit 2c09368273
16 changed files with 255 additions and 15 deletions

View File

@@ -3491,6 +3491,10 @@ gui_init_which_components(char_u *oldval UNUSED)
#ifdef FEAT_GUI_TABLINE
int using_tabline;
#endif
#ifdef FEAT_GUI_MSWIN
static int prev_titlebar = -1;
int using_titlebar = FALSE;
#endif
#if defined(FEAT_MENU)
static int prev_tearoff = -1;
int using_tearoff = FALSE;
@@ -3560,6 +3564,11 @@ gui_init_which_components(char_u *oldval UNUSED)
case GO_GREY:
// make menu's have grey items, ignored here
break;
#ifdef FEAT_GUI_MSWIN
case GO_TITLEBAR:
using_titlebar = TRUE;
break;
#endif
#ifdef FEAT_TOOLBAR
case GO_TOOLBAR:
using_toolbar = TRUE;
@@ -3581,6 +3590,14 @@ gui_init_which_components(char_u *oldval UNUSED)
need_set_size = 0;
fix_size = FALSE;
#ifdef FEAT_GUI_MSWIN
if (using_titlebar != prev_titlebar)
{
gui_mch_set_titlebar_colors();
prev_titlebar = using_titlebar;
}
#endif
#ifdef FEAT_GUI_DARKTHEME
if (using_dark_theme != prev_dark_theme)
{
@@ -4751,6 +4768,10 @@ gui_focus_change(int in_focus)
gui.in_focus = in_focus;
out_flush_cursor(TRUE, FALSE);
# ifdef FEAT_GUI_MSWIN
gui_mch_set_titlebar_colors();
# endif
# ifdef FEAT_XIM
xim_set_focus(in_focus);
# endif

View File

@@ -422,6 +422,11 @@ typedef struct Gui
guicolor_T currFgColor; // Current foreground text color
guicolor_T currBgColor; // Current background text color
guicolor_T currSpColor; // Current special text color
guicolor_T title_bg_pixel; // window title bar color
guicolor_T title_fg_pixel; // window title bar's text color
guicolor_T titlenc_bg_pixel; // window title bar color not current
guicolor_T titlenc_fg_pixel; // window title bar's text color not current
#endif
#ifdef FEAT_GUI_HAIKU

View File

@@ -318,6 +318,14 @@ gui_mch_set_rendering_options(char_u *s)
# define SPI_SETWHEELSCROLLCHARS 0x006D
#endif
#ifndef DWMWA_CAPTION_COLOR
# define DWMWA_CAPTION_COLOR 35
#endif
#ifndef DWMWA_TEXT_COLOR
# define DWMWA_TEXT_COLOR 36
#endif
#ifdef PROTO
/*
* Define a few things for generating prototypes. This is just to avoid
@@ -468,6 +476,10 @@ static int (WINAPI *pGetSystemMetricsForDpi)(int, UINT) = NULL;
static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext) = NULL;
static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT) = NULL;
static HINSTANCE hLibDwm = NULL;
static HRESULT (WINAPI *pDwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD);
static void dyn_dwm_load(void);
static int WINAPI
stubGetSystemMetricsForDpi(int nIndex, UINT dpi UNUSED)
{
@@ -1591,6 +1603,67 @@ _TextAreaWndProc(
}
}
static void
dyn_dwm_load(void)
{
hLibDwm = vimLoadLib("dwmapi.dll");
if (hLibDwm == NULL)
return;
pDwmSetWindowAttribute = (HRESULT (WINAPI *)(HWND, DWORD, LPCVOID, DWORD))
GetProcAddress(hLibDwm, "DwmSetWindowAttribute");
if (pDwmSetWindowAttribute == NULL)
{
FreeLibrary(hLibDwm);
hLibDwm = NULL;
return;
}
}
extern BOOL win11_or_later; // this is in os_win32.c
/*
* Set TitleBar's color. Handle hl-TitleBar and hl-TitleBarNC.
*
* Only enabled when 'guioptions' has 'C'.
* if "TitleBar guibg=NONE guifg=NONE" reset the window back to using the
* system's default behavior for the border color.
*/
void
gui_mch_set_titlebar_colors(void)
{
if (pDwmSetWindowAttribute == NULL || !win11_or_later)
return;
guicolor_T captionColor = 0xFFFFFFFF;
guicolor_T textColor = 0xFFFFFFFF;
if (vim_strchr(p_go, GO_TITLEBAR) != NULL)
{
if (gui.in_focus)
{
captionColor = gui.title_bg_pixel;
textColor = gui.title_fg_pixel;
}
else
{
captionColor = gui.titlenc_bg_pixel;
textColor = gui.titlenc_fg_pixel;
}
if (captionColor == INVALCOLOR)
captionColor = 0xFFFFFFFF;
if (textColor == INVALCOLOR)
textColor = 0xFFFFFFFF;
}
pDwmSetWindowAttribute(s_hwnd, DWMWA_CAPTION_COLOR,
&captionColor, sizeof(captionColor));
pDwmSetWindowAttribute(s_hwnd, DWMWA_TEXT_COLOR,
&textColor, sizeof(textColor));
}
/*
* Called when the foreground or background color has been changed.
*/
@@ -5636,6 +5709,8 @@ gui_mch_init(void)
load_dpi_func();
dyn_dwm_load();
s_dpi = pGetDpiForSystem();
update_scrollbar_size();

View File

@@ -255,6 +255,10 @@ static char *(highlight_init_both[]) = {
#ifdef FEAT_GUI
"Cursor guibg=fg guifg=bg",
"lCursor guibg=fg guifg=bg", // should be different, but what?
#endif
#ifdef FEAT_GUI_MSWIN
"TitleBar guibg=bg guifg=fg",
"TitleBarNC guibg=NONE guifg=NONE",
#endif
"default link QuickFixLine Search",
"default link CursorLineSign SignColumn",
@@ -817,6 +821,10 @@ highlight_reset_all(void)
# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_X11)
gui_mch_def_colors();
# endif
# ifdef FEAT_GUI_MSWIN
if (gui.in_use)
gui_mch_set_titlebar_colors();
# endif
# ifdef FEAT_GUI_X11
# ifdef FEAT_MENU
@@ -1272,6 +1280,8 @@ highlight_set_guifg(
int is_menu_group UNUSED,
int is_scrollbar_group UNUSED,
int is_tooltip_group UNUSED,
int is_titlebar_group UNUSED,
int is_titlebarnc_group UNUSED,
int *do_colors UNUSED,
int init)
{
@@ -1305,6 +1315,18 @@ highlight_set_guifg(
did_change = TRUE;
}
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
# ifdef FEAT_GUI_MSWIN
if (is_titlebar_group && gui.title_fg_pixel != i)
{
gui.title_fg_pixel = i;
*do_colors = TRUE;
}
if (is_titlebarnc_group && gui.titlenc_fg_pixel != i)
{
gui.titlenc_fg_pixel = i;
*do_colors = TRUE;
}
# endif
# ifdef FEAT_GUI_X11
if (is_menu_group && gui.menu_fg_pixel != i)
{
@@ -1341,6 +1363,8 @@ highlight_set_guibg(
int is_menu_group UNUSED,
int is_scrollbar_group UNUSED,
int is_tooltip_group UNUSED,
int is_titlebar_group UNUSED,
int is_titlebarnc_group UNUSED,
int *do_colors UNUSED,
int init)
{
@@ -1374,6 +1398,18 @@ highlight_set_guibg(
did_change = TRUE;
}
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
# ifdef FEAT_GUI_MSWIN
if (is_titlebar_group && gui.title_bg_pixel != i)
{
gui.title_bg_pixel = i;
*do_colors = TRUE;
}
if (is_titlebarnc_group && gui.titlenc_bg_pixel != i)
{
gui.titlenc_bg_pixel = i;
*do_colors = TRUE;
}
# endif
# ifdef FEAT_GUI_X11
if (is_menu_group && gui.menu_bg_pixel != i)
{
@@ -1551,6 +1587,13 @@ do_highlight(
int dolink = FALSE;
int error = FALSE;
int is_normal_group = FALSE; // "Normal" group
#ifdef FEAT_GUI_MSWIN
int is_titlebar_group = FALSE; // "TitleBar" group
int is_titlebarnc_group = FALSE; // "TitleBarNC" group
#else
# define is_titlebar_group 0
# define is_titlebarnc_group 0
#endif
#ifdef FEAT_GUI_X11
int is_menu_group = FALSE; // "Menu" group
int is_scrollbar_group = FALSE; // "Scrollbar" group
@@ -1668,6 +1711,12 @@ do_highlight(
if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0)
is_normal_group = TRUE;
#ifdef FEAT_GUI_MSWIN
else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TITLEBAR") == 0)
is_titlebar_group = TRUE;
else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TITLEBARNC") == 0)
is_titlebarnc_group = TRUE;
#endif
#ifdef FEAT_GUI_X11
else if (STRCMP(HL_TABLE()[idx].sg_name_u, "MENU") == 0)
is_menu_group = TRUE;
@@ -1808,8 +1857,9 @@ do_highlight(
{
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (highlight_set_guifg(idx, arg, is_menu_group,
is_scrollbar_group, is_tooltip_group,
&do_colors, init))
is_scrollbar_group, is_tooltip_group,
is_titlebar_group, is_titlebarnc_group,
&do_colors, init))
did_change = TRUE;
#endif
}
@@ -1818,6 +1868,7 @@ do_highlight(
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (highlight_set_guibg(idx, arg, is_menu_group,
is_scrollbar_group, is_tooltip_group,
is_titlebar_group, is_titlebarnc_group,
&do_colors, init))
did_change = TRUE;
#endif
@@ -1879,6 +1930,18 @@ do_highlight(
control_console_color_rgb();
#endif
}
#ifdef FEAT_GUI_MSWIN
else if (is_titlebar_group)
{
if (gui.in_use && do_colors)
gui_mch_set_titlebar_colors();
}
else if (is_titlebarnc_group)
{
if (gui.in_use && do_colors)
gui_mch_set_titlebar_colors();
}
#endif
#ifdef FEAT_GUI_X11
# ifdef FEAT_MENU
else if (is_menu_group)
@@ -2052,8 +2115,8 @@ highlight_clear(int idx)
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) || defined(PROTO)
/*
* Set the normal foreground and background colors according to the "Normal"
* highlighting group. For X11 also set "Menu", "Scrollbar", and
* "Tooltip" colors.
* highlighting group. For X11 also set "Menu", "Scrollbar" and "Tooltip"
* colors. For MS-Windows also set "TitleBar" and "TitleBarNC" colors.
*/
void
set_normal_colors(void)
@@ -2070,6 +2133,22 @@ set_normal_colors(void)
gui_mch_new_colors();
set_must_redraw(UPD_CLEAR);
}
# ifdef FEAT_GUI_MSWIN
if (set_group_colors((char_u *)"TitleBar",
&gui.title_fg_pixel, &gui.title_bg_pixel,
FALSE, FALSE, FALSE))
{
gui_mch_set_titlebar_colors();
set_must_redraw(UPD_CLEAR);
}
if (set_group_colors((char_u *)"TitleBarNC",
&gui.titlenc_fg_pixel, &gui.titlenc_bg_pixel,
FALSE, FALSE, FALSE))
{
gui_mch_set_titlebar_colors();
set_must_redraw(UPD_CLEAR);
}
# endif
# ifdef FEAT_GUI_X11
if (set_group_colors((char_u *)"Menu",
&gui.menu_fg_pixel, &gui.menu_bg_pixel,
@@ -2132,7 +2211,8 @@ set_normal_colors(void)
#if defined(FEAT_GUI) || defined(PROTO)
/*
* Set the colors for "Normal", "Menu", "Tooltip" or "Scrollbar".
* Set the colors for "Normal", "Menu", "TitleBar", "TitleBarNC", "Tooltip" or
* "Scrollbar".
*/
static int
set_group_colors(

View File

@@ -288,6 +288,7 @@ typedef enum {
#define GO_ASELML 'A' // autoselect modeless selection
#define GO_BOT 'b' // use bottom scrollbar
#define GO_CONDIALOG 'c' // use console dialog
#define GO_TITLEBAR 'C' // use 'hl-TitleBar'
#define GO_DARKTHEME 'd' // use dark theme variant
#define GO_TABLINE 'e' // may show tabline
#define GO_FORG 'f' // start GUI in foreground
@@ -308,7 +309,7 @@ typedef enum {
#define GO_VERTICAL 'v' // arrange dialog buttons vertically
#define GO_KEEPWINSIZE 'k' // keep GUI window size
// all possible flags for 'go'
#define GO_ALL "!aAbcdefFghilLmMpPrRtTvk"
#define GO_ALL "!aAbcCdefFghilLmMpPrRtTvk"
// flags for 'comments' option
#define COM_NEST 'n' // comments strings nest

View File

@@ -224,6 +224,8 @@ static WCHAR *exe_pathw = NULL;
static BOOL win8_or_later = FALSE;
static BOOL win10_22H2_or_later = FALSE;
BOOL win11_or_later = FALSE; // used in gui_mch_set_titlebar_colors(void)
#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
static BOOL use_alternate_screen_buffer = FALSE;
#endif
@@ -1010,6 +1012,10 @@ PlatformId(void)
|| ovi.dwMajorVersion > 10)
win10_22H2_or_later = TRUE;
if ((ovi.dwMajorVersion == 10 && ovi.dwBuildNumber >= 22000)
|| ovi.dwMajorVersion > 10)
win11_or_later = TRUE;
#ifdef HAVE_ACL
// Enable privilege for getting or setting SACLs.
if (!win32_enable_privilege(SE_SECURITY_NAME))

View File

@@ -5,6 +5,7 @@ int gui_mch_is_blink_off(void);
void gui_mch_set_blinking(long wait, long on, long off);
void gui_mch_stop_blink(int may_call_gui_update_cursor);
void gui_mch_start_blink(void);
void gui_mch_set_titlebar_colors(void);
void gui_mch_new_colors(void);
void gui_mch_def_colors(void);
int gui_mch_open(void);

View File

@@ -664,6 +664,13 @@ func Test_set_guioptions()
set guioptions&
call assert_equal('egmrLtT', &guioptions)
set guioptions+=C
exec 'sleep' . duration
call assert_equal('egmrLtTC', &guioptions)
set guioptions-=C
exec 'sleep' . duration
call assert_equal('egmrLtT', &guioptions)
else
" Default Value
set guioptions&

View File

@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1834,
/**/
1833,
/**/