Skip to content

Commit 75d5802

Browse files
mao-yiningLemonBoy
andcommitted
feat: support dark mode on MS-Windows
Problem: dark mode for MS-Windows is not supported Solution: Inplement the 'd' flag in 'guioptions' on MS-Windows Co-Authored-By: LemonBoy <thatlemon@gmail.com> Signed-off-by: Mao-Yining <mao.yining@outlook.com>
1 parent b60b33a commit 75d5802

File tree

8 files changed

+70
-6
lines changed

8 files changed

+70
-6
lines changed

runtime/doc/options.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4526,7 +4526,7 @@ A jump table for the options with a short description can be found at |Q_op|.
45264526
See |gui-w32-title-bar| for details.
45274527
*'go-d'*
45284528
'd' Use dark theme variant if available. Currently only works for
4529-
GTK+ GUI.
4529+
Win32 and GTK+ GUI.
45304530
*'go-e'*
45314531
'e' Add tab pages when indicated with 'showtabline'.
45324532
'guitablabel' can be used to change the text in the labels.

runtime/doc/todo.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,6 @@ Problem with Visual highlight when 'linebreak' and 'showbreak' are set.
309309
GUI Scroll test fails on FreeBSD when using Motif. See FIXME in
310310
Test_scrollbars in src/test_gui.vim
311311

312-
Support dark mode for MS-Windows: #12282
313-
314312
Remote command escapes single quote with backslash, should be doubling the
315313
single quote in vim_strsave_escaped_ext() #12202.
316314

src/feature.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@
508508
/*
509509
* GUI dark theme variant
510510
*/
511-
#if defined(FEAT_GUI_GTK) && defined(USE_GTK3)
511+
#if (defined(FEAT_GUI_GTK) && defined(USE_GTK3)) || defined(FEAT_GUI_MSWIN)
512512
# define FEAT_GUI_DARKTHEME
513513
#endif
514514

src/gui.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3480,7 +3480,7 @@ static int prev_which_scrollbars[3];
34803480
gui_init_which_components(char_u *oldval UNUSED)
34813481
{
34823482
#ifdef FEAT_GUI_DARKTHEME
3483-
static int prev_dark_theme = -1;
3483+
static int prev_dark_theme = FALSE;
34843484
int using_dark_theme = FALSE;
34853485
#endif
34863486
#ifdef FEAT_MENU

src/gui_w32.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@ gui_mch_set_rendering_options(char_u *s)
315315
# define SPI_SETWHEELSCROLLCHARS 0x006D
316316
#endif
317317

318+
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
319+
# define DWMWA_USE_IMMERSIVE_DARK_MODE 20
320+
#endif
321+
318322
#ifndef DWMWA_CAPTION_COLOR
319323
# define DWMWA_CAPTION_COLOR 35
320324
#endif
@@ -417,6 +421,14 @@ static HINSTANCE hLibDwm = NULL;
417421
static HRESULT (WINAPI *pDwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD);
418422
static void dyn_dwm_load(void);
419423

424+
#ifdef FEAT_GUI_DARKTHEME
425+
426+
static HINSTANCE hUxThemeLib = NULL;
427+
static DWORD (WINAPI *pSetPreferredAppMode)(DWORD) = NULL;
428+
static void (WINAPI *pFlushMenuThemes)(void) = NULL;
429+
static void dyn_uxtheme_load(void);
430+
#endif
431+
420432
static int WINAPI
421433
stubGetSystemMetricsForDpi(int nIndex, UINT dpi UNUSED)
422434
{
@@ -3116,6 +3128,48 @@ gui_mch_set_curtab(int nr)
31163128

31173129
#endif
31183130

3131+
#ifdef FEAT_GUI_DARKTHEME
3132+
extern BOOL win10_22H2_or_later; // this is in os_win32.c
3133+
3134+
void
3135+
gui_mch_set_dark_theme(int dark)
3136+
{
3137+
if (!win10_22H2_or_later)
3138+
return;
3139+
3140+
if (pDwmSetWindowAttribute != NULL)
3141+
pDwmSetWindowAttribute(s_hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark,
3142+
sizeof(dark));
3143+
3144+
if (pSetPreferredAppMode != NULL)
3145+
pSetPreferredAppMode(dark);
3146+
3147+
if (pFlushMenuThemes != NULL)
3148+
pFlushMenuThemes();
3149+
}
3150+
3151+
static void
3152+
dyn_uxtheme_load(void)
3153+
{
3154+
hUxThemeLib = vimLoadLib("uxtheme.dll");
3155+
if (hUxThemeLib == NULL)
3156+
return;
3157+
3158+
pSetPreferredAppMode = (DWORD (WINAPI *)(DWORD))
3159+
GetProcAddress(hUxThemeLib, MAKEINTRESOURCE(135));
3160+
pFlushMenuThemes = (void (WINAPI *)(void))
3161+
GetProcAddress(hUxThemeLib, MAKEINTRESOURCE(136));
3162+
3163+
if (pSetPreferredAppMode == NULL || pFlushMenuThemes == NULL)
3164+
{
3165+
FreeLibrary(hUxThemeLib);
3166+
hUxThemeLib = NULL;
3167+
return;
3168+
}
3169+
}
3170+
3171+
#endif // FEAT_GUI_DARKTHEME
3172+
31193173
/*
31203174
* ":simalt" command.
31213175
*/
@@ -5646,6 +5700,10 @@ gui_mch_init(void)
56465700

56475701
load_dpi_func();
56485702

5703+
#ifdef FEAT_GUI_DARKTHEME
5704+
dyn_uxtheme_load();
5705+
#endif
5706+
56495707
dyn_dwm_load();
56505708

56515709
s_dpi = pGetDpiForSystem();

src/os_win32.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ static int suppress_winsize = 1; // don't fiddle with console
161161
static WCHAR *exe_pathw = NULL;
162162

163163
static BOOL win8_or_later = FALSE;
164-
static BOOL win10_22H2_or_later = FALSE;
164+
BOOL win10_22H2_or_later = FALSE;
165165
BOOL win11_or_later = FALSE; // used in gui_mch_set_titlebar_colors(void)
166166

167167
#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)

src/proto/gui_w32.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ void gui_mch_set_blinking(long wait, long on, long off);
66
void gui_mch_stop_blink(int may_call_gui_update_cursor);
77
void gui_mch_start_blink(void);
88
void gui_mch_set_titlebar_colors(void);
9+
void gui_mch_set_dark_theme(int dark);
910
void gui_mch_new_colors(void);
1011
void gui_mch_def_colors(void);
1112
int gui_mch_open(void);

src/testdir/test_gui.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,13 @@ func Test_set_guioptions()
671671
exec 'sleep' . duration
672672
call assert_equal('egmrLtT', &guioptions)
673673

674+
set guioptions+=d
675+
exec 'sleep' . duration
676+
call assert_equal('egmrLtTd', &guioptions)
677+
set guioptions-=d
678+
exec 'sleep' . duration
679+
call assert_equal('egmrLtT', &guioptions)
680+
674681
else
675682
" Default Value
676683
set guioptions&

0 commit comments

Comments
 (0)