diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d7adf555ab..0017864564 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4527,7 +4527,7 @@ A jump table for the options with a short description can be found at |Q_op|. See |gui-w32-title-bar| for details. *'go-d'* 'd' Use dark theme variant if available. Currently only works for - GTK+ GUI. + Win32 and GTK+ GUI. *'go-e'* 'e' Add tab pages when indicated with 'showtabline'. 'guitablabel' can be used to change the text in the labels. diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 5b4e49a4b2..d684f78c2c 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 9.1. Last change: 2025 Nov 18 +*todo.txt* For Vim version 9.1. Last change: 2025 Dec 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -309,8 +309,6 @@ Problem with Visual highlight when 'linebreak' and 'showbreak' are set. GUI Scroll test fails on FreeBSD when using Motif. See FIXME in Test_scrollbars in src/test_gui.vim -Support dark mode for MS-Windows: #12282 - Remote command escapes single quote with backslash, should be doubling the single quote in vim_strsave_escaped_ext() #12202. diff --git a/src/feature.h b/src/feature.h index 11700a060d..cbb1875fdd 100644 --- a/src/feature.h +++ b/src/feature.h @@ -508,7 +508,7 @@ /* * GUI dark theme variant */ -#if defined(FEAT_GUI_GTK) && defined(USE_GTK3) +#if (defined(FEAT_GUI_GTK) && defined(USE_GTK3)) || defined(FEAT_GUI_MSWIN) # define FEAT_GUI_DARKTHEME #endif diff --git a/src/gui.c b/src/gui.c index 4f658c828f..9487fd1930 100644 --- a/src/gui.c +++ b/src/gui.c @@ -3480,7 +3480,7 @@ static int prev_which_scrollbars[3]; gui_init_which_components(char_u *oldval UNUSED) { #ifdef FEAT_GUI_DARKTHEME - static int prev_dark_theme = -1; + static int prev_dark_theme = FALSE; int using_dark_theme = FALSE; #endif #ifdef FEAT_MENU diff --git a/src/gui_w32.c b/src/gui_w32.c index abaa766c36..290223c44e 100644 --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -315,6 +315,10 @@ gui_mch_set_rendering_options(char_u *s) # define SPI_SETWHEELSCROLLCHARS 0x006D #endif +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +# define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + #ifndef DWMWA_CAPTION_COLOR # define DWMWA_CAPTION_COLOR 35 #endif @@ -417,6 +421,14 @@ static HINSTANCE hLibDwm = NULL; static HRESULT (WINAPI *pDwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD); static void dyn_dwm_load(void); +#ifdef FEAT_GUI_DARKTHEME + +static HINSTANCE hUxThemeLib = NULL; +static DWORD (WINAPI *pSetPreferredAppMode)(DWORD) = NULL; +static void (WINAPI *pFlushMenuThemes)(void) = NULL; +static void dyn_uxtheme_load(void); +#endif + static int WINAPI stubGetSystemMetricsForDpi(int nIndex, UINT dpi UNUSED) { @@ -3116,6 +3128,48 @@ gui_mch_set_curtab(int nr) #endif +#ifdef FEAT_GUI_DARKTHEME +extern BOOL win10_22H2_or_later; // this is in os_win32.c + + void +gui_mch_set_dark_theme(int dark) +{ + if (!win10_22H2_or_later) + return; + + if (pDwmSetWindowAttribute != NULL) + pDwmSetWindowAttribute(s_hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark, + sizeof(dark)); + + if (pSetPreferredAppMode != NULL) + pSetPreferredAppMode(dark); + + if (pFlushMenuThemes != NULL) + pFlushMenuThemes(); +} + + static void +dyn_uxtheme_load(void) +{ + hUxThemeLib = vimLoadLib("uxtheme.dll"); + if (hUxThemeLib == NULL) + return; + + pSetPreferredAppMode = (DWORD (WINAPI *)(DWORD)) + GetProcAddress(hUxThemeLib, MAKEINTRESOURCE(135)); + pFlushMenuThemes = (void (WINAPI *)(void)) + GetProcAddress(hUxThemeLib, MAKEINTRESOURCE(136)); + + if (pSetPreferredAppMode == NULL || pFlushMenuThemes == NULL) + { + FreeLibrary(hUxThemeLib); + hUxThemeLib = NULL; + return; + } +} + +#endif // FEAT_GUI_DARKTHEME + /* * ":simalt" command. */ @@ -5646,6 +5700,10 @@ gui_mch_init(void) load_dpi_func(); +#ifdef FEAT_GUI_DARKTHEME + dyn_uxtheme_load(); +#endif + dyn_dwm_load(); s_dpi = pGetDpiForSystem(); diff --git a/src/os_win32.c b/src/os_win32.c index 35d69c119c..21b7023fa3 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -161,7 +161,7 @@ static int suppress_winsize = 1; // don't fiddle with console static WCHAR *exe_pathw = NULL; static BOOL win8_or_later = FALSE; -static BOOL win10_22H2_or_later = FALSE; +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) diff --git a/src/proto/gui_w32.pro b/src/proto/gui_w32.pro index 41575084a2..83cb7721f0 100644 --- a/src/proto/gui_w32.pro +++ b/src/proto/gui_w32.pro @@ -43,6 +43,7 @@ void gui_mch_show_tabline(int showit); int gui_mch_showing_tabline(void); void gui_mch_update_tabline(void); void gui_mch_set_curtab(int nr); +void gui_mch_set_dark_theme(int dark); void ex_simalt(exarg_T *eap); void gui_mch_find_dialog(exarg_T *eap); void gui_mch_replace_dialog(exarg_T *eap); diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim index f1b3b234d8..1b7096b5d1 100644 --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -671,6 +671,13 @@ func Test_set_guioptions() exec 'sleep' . duration call assert_equal('egmrLtT', &guioptions) + set guioptions+=d + exec 'sleep' . duration + call assert_equal('egmrLtTd', &guioptions) + set guioptions-=d + exec 'sleep' . duration + call assert_equal('egmrLtT', &guioptions) + else " Default Value set guioptions& diff --git a/src/version.c b/src/version.c index beda34d856..9e5cfdcd55 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1966, /**/ 1965, /**/