]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1966: MS-Windows: dark mode in gui is not supported v9.1.1966
authorMao-Yining <mao.yining@outlook.com>
Tue, 9 Dec 2025 14:23:39 +0000 (15:23 +0100)
committerChristian Brabandt <cb@256bit.org>
Tue, 9 Dec 2025 14:23:39 +0000 (15:23 +0100)
Problem:  MS-Windows: dark mode in gui is not supported
Solution: Inplement the 'd' flag in 'guioptions'
          (Mao-Yining).

related: #12282
closes: #18877

Co-Authored-By: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Mao-Yining <mao.yining@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/options.txt
runtime/doc/todo.txt
src/feature.h
src/gui.c
src/gui_w32.c
src/os_win32.c
src/proto/gui_w32.pro
src/testdir/test_gui.vim
src/version.c

index d7adf555ab8d41e40d3bb766ebaa3c6b421398c3..0017864564743cf1ca89e9e77792dd1ba2148370 100644 (file)
@@ -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.
index 5b4e49a4b2fcbad806d4ee2e30519432536c8eed..d684f78c2c914a2605b4454899e896fb766f05f5 100644 (file)
@@ -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.
 
index 11700a060d6fa747d43ce27b2f8020f1f3b92c37..cbb1875fdde4513aff1cf079de2bc2ade46d2afe 100644 (file)
 /*
  * 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
 
index 4f658c828fa8af3a932c2792b08bcdd5169865ab..9487fd193041d68d093f8adb1a6793de2dea6063 100644 (file)
--- 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
index abaa766c3649e0dd5f503ba36fd6b13c7c6a7cc6..290223c44e843abd21ca53cede958eac108bda59 100644 (file)
@@ -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();
index 35d69c119c8cb7f9e60947314f08e041d7b54db6..21b7023fa39a23ff09082e132207d80292210879 100644 (file)
@@ -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)
index 41575084a2a30b2666dc3299d8ced9f901fd042b..83cb7721f0fdfbcb08b745bfbf8a741625f2e3df 100644 (file)
@@ -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);
index f1b3b234d8c6e9e0418c0d930848a24d9657990b..1b7096b5d1ca3b50a07cbfba5567d7eea5a59b5c 100644 (file)
@@ -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&
index beda34d85618cb269e928d85254d8dcaf4186d02..9e5cfdcd557db8188b2583890f532fac8779eb6e 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1966,
 /**/
     1965,
 /**/