comparison win/dw.c @ 2099:296a3872ddd9

Added a fourth dark mode option on Windows: Disabled, Basic, Full, Forced. Disabled (0) forces dark mode off on Mac and Windows. Enabled (1) System decides but only window frame is dark mode on Windows. Full (2) System decides but everything that can be dark is on Mac and Windows. Forced (3) Force dark mode on Mac and Windows regardless of system setting. Enabled (1) and Full (2) are identical on Mac. Added code to enable full dark mode in the test program. Several widgets are not able to go dark on Windows currently: Notebook, Menubar
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 12 Jun 2020 20:40:47 +0000
parents 665d87a50eac
children 12a9546c3e03
comparison
equal deleted inserted replaced
2098:665d87a50eac 2099:296a3872ddd9
691 691
692 #ifdef AEROGLASS 692 #ifdef AEROGLASS
693 /* Set _DW_DARK_MODE_ALLOWED to FALSE to disable dark mode. 693 /* Set _DW_DARK_MODE_ALLOWED to FALSE to disable dark mode.
694 * Set _DW_DARK_MODE_ALLOWED to TRUE for basic dark mode. 694 * Set _DW_DARK_MODE_ALLOWED to TRUE for basic dark mode.
695 * Set _DW_DARK_MODE_ALLOWED to 2 for full dark mode. 695 * Set _DW_DARK_MODE_ALLOWED to 2 for full dark mode.
696 * Set _DW_DARK_MODE_ALLOWED to 3 for forced full dark mode.
696 */ 697 */
697 int _DW_DARK_MODE_ALLOWED = TRUE; 698 int _DW_DARK_MODE_ALLOWED = TRUE;
698 int _DW_DARK_MODE_SUPPORTED = FALSE; 699 int _DW_DARK_MODE_SUPPORTED = FALSE;
699 int _DW_DARK_MODE_ENABLED = FALSE; 700 int _DW_DARK_MODE_ENABLED = FALSE;
700 701
769 if(SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE)) 770 if(SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE))
770 return highContrast.dwFlags & HCF_HIGHCONTRASTON; 771 return highContrast.dwFlags & HCF_HIGHCONTRASTON;
771 return FALSE; 772 return FALSE;
772 } 773 }
773 774
775 /* Our own ShouldAppsUseDarkMode() that handles the forced option */
776 BOOL _DW_ShouldAppsUseDarkMode(void)
777 {
778 if(_DW_DARK_MODE_ALLOWED == 3)
779 return TRUE;
780 return (_ShouldAppsUseDarkMode() && !IsHighContrast());
781 }
782
774 void _dw_init_dark_mode(void) 783 void _dw_init_dark_mode(void)
775 { 784 {
776 if(_DW_DARK_MODE_ALLOWED && dwVersion && huxtheme) 785 if(_DW_DARK_MODE_ALLOWED && dwVersion && huxtheme)
777 { 786 {
778 /* Dark mode is introduced in Windows 10 (1809) build 17763 */ 787 /* Dark mode is introduced in Windows 10 (1809) build 17763 */
800 if(_AllowDarkModeForApp) 809 if(_AllowDarkModeForApp)
801 _AllowDarkModeForApp(TRUE); 810 _AllowDarkModeForApp(TRUE);
802 else 811 else
803 _SetPreferredAppMode(_AllowDark); 812 _SetPreferredAppMode(_AllowDark);
804 _RefreshImmersiveColorPolicyState(); 813 _RefreshImmersiveColorPolicyState();
805 _DW_DARK_MODE_ENABLED = _ShouldAppsUseDarkMode() && !IsHighContrast(); 814 _DW_DARK_MODE_ENABLED = _DW_ShouldAppsUseDarkMode();
806 } 815 }
807 } 816 }
808 } 817 }
809 818
810 BOOL _CanThemeWindow(HWND window) 819 BOOL _CanThemeWindow(HWND window)
820 return FALSE; 829 return FALSE;
821 #ifdef TOOLBAR 830 #ifdef TOOLBAR
822 else if(_tcsnicmp(tmpbuf, TOOLBARCLASSNAME, _tcslen(TOOLBARCLASSNAME)+1) == 0) 831 else if(_tcsnicmp(tmpbuf, TOOLBARCLASSNAME, _tcslen(TOOLBARCLASSNAME)+1) == 0)
823 { 832 {
824 /* If we aren't in full dark mode */ 833 /* If we aren't in full dark mode */
825 if(_DW_DARK_MODE_ALLOWED != 2) 834 if(_DW_DARK_MODE_ALLOWED < 2)
826 { 835 {
827 /* Enable or disable visual themes */ 836 /* Enable or disable visual themes */
828 if(_SetWindowTheme) 837 if(_SetWindowTheme)
829 _SetWindowTheme(window, (style & TBSTYLE_FLAT) ? L"" : NULL, (style & TBSTYLE_FLAT) ? L"" : NULL); 838 _SetWindowTheme(window, (style & TBSTYLE_FLAT) ? L"" : NULL, (style & TBSTYLE_FLAT) ? L"" : NULL);
830 } 839 }
838 { 847 {
839 if(_DW_DARK_MODE_SUPPORTED) 848 if(_DW_DARK_MODE_SUPPORTED)
840 { 849 {
841 if(_CanThemeWindow(window)) 850 if(_CanThemeWindow(window))
842 { 851 {
843 if(_DW_DARK_MODE_ALLOWED == 2) 852 if(_DW_DARK_MODE_ALLOWED > 1)
844 { 853 {
845 if(_DW_DARK_MODE_ENABLED) 854 if(_DW_DARK_MODE_ENABLED)
846 _SetWindowTheme(window, L"DarkMode_Explorer", NULL); 855 _SetWindowTheme(window, L"DarkMode_Explorer", NULL);
847 else 856 else
848 _SetWindowTheme(window, L"Explorer", NULL); 857 _SetWindowTheme(window, L"Explorer", NULL);
866 } 875 }
867 876
868 void RefreshTitleBarThemeColor(HWND window) 877 void RefreshTitleBarThemeColor(HWND window)
869 { 878 {
870 BOOL dark = FALSE; 879 BOOL dark = FALSE;
871 if (_IsDarkModeAllowedForWindow(window) && _ShouldAppsUseDarkMode() && !IsHighContrast()) 880 if (_IsDarkModeAllowedForWindow(window) && _DW_ShouldAppsUseDarkMode())
872 dark = TRUE; 881 dark = TRUE;
873 if(HIWORD(dwVersion) < 18362) 882 if(HIWORD(dwVersion) < 18362)
874 SetProp(window, TEXT("UseImmersiveDarkModeColors"), (HANDLE)DW_INT_TO_POINTER(dark)); 883 SetProp(window, TEXT("UseImmersiveDarkModeColors"), (HANDLE)DW_INT_TO_POINTER(dark));
875 else if (_SetWindowCompositionAttribute) 884 else if (_SetWindowCompositionAttribute)
876 { 885 {
897 */ 906 */
898 DWORD _DW_GetSysColor(int nIndex) 907 DWORD _DW_GetSysColor(int nIndex)
899 { 908 {
900 DWORD retval = GetSysColor(nIndex); 909 DWORD retval = GetSysColor(nIndex);
901 #ifdef AEROGLASS 910 #ifdef AEROGLASS
902 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) 911 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_ENABLED)
903 { 912 {
904 const COLORREF darkBkColor = 0x383838; 913 const COLORREF darkBkColor = 0x383838;
905 const COLORREF darkTextColor = 0xFFFFFF; 914 const COLORREF darkTextColor = 0xFFFFFF;
906 915
907 switch(nIndex) 916 switch(nIndex)
923 { 932 {
924 HBRUSH retval = GetSysColorBrush(nIndex); 933 HBRUSH retval = GetSysColorBrush(nIndex);
925 #ifdef AEROGLASS 934 #ifdef AEROGLASS
926 static HBRUSH darkBkColorBrush = 0; 935 static HBRUSH darkBkColorBrush = 0;
927 936
928 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) 937 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_ENABLED)
929 { 938 {
930 if(!darkBkColorBrush) 939 if(!darkBkColorBrush)
931 darkBkColorBrush = CreateSolidBrush(0x383838); 940 darkBkColorBrush = CreateSolidBrush(0x383838);
932 941
933 switch(nIndex) 942 switch(nIndex)
2498 break; 2507 break;
2499 case WM_SETTINGCHANGE: 2508 case WM_SETTINGCHANGE:
2500 { 2509 {
2501 if(_DW_DARK_MODE_SUPPORTED && IsColorSchemeChangeMessage(mp2)) 2510 if(_DW_DARK_MODE_SUPPORTED && IsColorSchemeChangeMessage(mp2))
2502 { 2511 {
2503 _DW_DARK_MODE_ENABLED = _ShouldAppsUseDarkMode() && !IsHighContrast(); 2512 _DW_DARK_MODE_ENABLED = _DW_ShouldAppsUseDarkMode();
2504 2513
2505 RefreshTitleBarThemeColor(hWnd); 2514 RefreshTitleBarThemeColor(hWnd);
2506 _dw_set_child_window_theme(hWnd, 0); 2515 _dw_set_child_window_theme(hWnd, 0);
2507 EnumChildWindows(hWnd, _dw_set_child_window_theme, 0); 2516 EnumChildWindows(hWnd, _dw_set_child_window_theme, 0);
2508 } 2517 }
2708 case WM_MOUSEMOVE: 2717 case WM_MOUSEMOVE:
2709 _wndproc(hWnd, msg, mp1, mp2); 2718 _wndproc(hWnd, msg, mp1, mp2);
2710 break; 2719 break;
2711 #ifdef AEROGLASS 2720 #ifdef AEROGLASS
2712 case WM_THEMECHANGED: 2721 case WM_THEMECHANGED:
2713 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) 2722 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_SUPPORTED)
2714 { 2723 {
2715 SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)_DW_GetSysColorBrush(COLOR_3DFACE)); 2724 SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)_DW_GetSysColorBrush(COLOR_3DFACE));
2716 InvalidateRect(hWnd, NULL, TRUE); 2725 InvalidateRect(hWnd, NULL, TRUE);
2717 } 2726 }
2718 break; 2727 break;
3163 SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(fore), 3172 SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(fore),
3164 DW_GREEN_VALUE(fore), 3173 DW_GREEN_VALUE(fore),
3165 DW_BLUE_VALUE(fore))); 3174 DW_BLUE_VALUE(fore)));
3166 } 3175 }
3167 #ifdef AEROGLASS 3176 #ifdef AEROGLASS
3168 else if(thiscinfo->fore == DW_CLR_DEFAULT && _DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) 3177 else if(thiscinfo->fore == DW_CLR_DEFAULT && _DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_ENABLED)
3169 SetTextColor((HDC)mp1, _DW_GetSysColor(COLOR_WINDOWTEXT)); 3178 SetTextColor((HDC)mp1, _DW_GetSysColor(COLOR_WINDOWTEXT));
3170 #endif 3179 #endif
3171 /* Handle background */ 3180 /* Handle background */
3172 if(thiscinfo->back == DW_RGB_TRANSPARENT) 3181 if(thiscinfo->back == DW_RGB_TRANSPARENT)
3173 { 3182 {
3234 case WM_CTLCOLOREDIT: 3243 case WM_CTLCOLOREDIT:
3235 case WM_CTLCOLORMSGBOX: 3244 case WM_CTLCOLORMSGBOX:
3236 case WM_CTLCOLORSCROLLBAR: 3245 case WM_CTLCOLORSCROLLBAR:
3237 case WM_CTLCOLORDLG: 3246 case WM_CTLCOLORDLG:
3238 { 3247 {
3239 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) 3248 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_ENABLED)
3240 { 3249 {
3241 ColorInfo *parentcinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); 3250 ColorInfo *parentcinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
3242 int thisback = thiscinfo ? thiscinfo->back : -1; 3251 int thisback = thiscinfo ? thiscinfo->back : -1;
3243 3252
3244 if(thisback == DW_RGB_TRANSPARENT && parentcinfo) 3253 if(thisback == DW_RGB_TRANSPARENT && parentcinfo)
3285 case WM_MOUSEMOVE: 3294 case WM_MOUSEMOVE:
3286 _wndproc(hWnd, msg, mp1, mp2); 3295 _wndproc(hWnd, msg, mp1, mp2);
3287 break; 3296 break;
3288 #ifdef AEROGLASS 3297 #ifdef AEROGLASS
3289 case WM_THEMECHANGED: 3298 case WM_THEMECHANGED:
3290 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) 3299 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_SUPPORTED)
3291 { 3300 {
3292 if(!continfo || continfo->cinfo.back == -1 || continfo->cinfo.back == DW_CLR_DEFAULT) 3301 if(!continfo || continfo->cinfo.back == -1 || continfo->cinfo.back == DW_CLR_DEFAULT)
3293 { 3302 {
3294 COLORREF bk = _DW_GetSysColor(COLOR_WINDOW); 3303 COLORREF bk = _DW_GetSysColor(COLOR_WINDOW);
3295 3304
3311 3320
3312 /* Create the colors based on the current theme */ 3321 /* Create the colors based on the current theme */
3313 if(continfo->odd == DW_CLR_DEFAULT) 3322 if(continfo->odd == DW_CLR_DEFAULT)
3314 { 3323 {
3315 #ifdef AEROGLASS 3324 #ifdef AEROGLASS
3316 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) 3325 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_ENABLED)
3317 odd = RGB(100,100,100); 3326 odd = RGB(100,100,100);
3318 else 3327 else
3319 #endif 3328 #endif
3320 odd = RGB(230, 230, 230); 3329 odd = RGB(230, 230, 230);
3321 } 3330 }
3498 LRESULT CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) 3507 LRESULT CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
3499 { 3508 {
3500 #ifdef AEROGLASS 3509 #ifdef AEROGLASS
3501 if(msg == WM_THEMECHANGED) 3510 if(msg == WM_THEMECHANGED)
3502 { 3511 {
3503 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) 3512 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_SUPPORTED)
3504 { 3513 {
3505 ContainerInfo *continfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA); 3514 ContainerInfo *continfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
3506 3515
3507 if(!continfo || continfo->cinfo.back == -1 || continfo->cinfo.back == DW_CLR_DEFAULT) 3516 if(!continfo || continfo->cinfo.back == -1 || continfo->cinfo.back == DW_CLR_DEFAULT)
3508 TreeView_SetBkColor(hWnd, _DW_GetSysColor(COLOR_WINDOW)); 3517 TreeView_SetBkColor(hWnd, _DW_GetSysColor(COLOR_WINDOW));
3670 case WM_ACTIVATE: 3679 case WM_ACTIVATE:
3671 case WM_SETFOCUS: 3680 case WM_SETFOCUS:
3672 return FALSE; 3681 return FALSE;
3673 #ifdef AEROGLASS 3682 #ifdef AEROGLASS
3674 case WM_THEMECHANGED: 3683 case WM_THEMECHANGED:
3675 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) 3684 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_SUPPORTED)
3676 InvalidateRect(hwnd, NULL, TRUE); 3685 InvalidateRect(hwnd, NULL, TRUE);
3677 break; 3686 break;
3678 #endif 3687 #endif
3679 case WM_PAINT: 3688 case WM_PAINT:
3680 { 3689 {
3782 InvalidateRgn(hwnd, NULL, TRUE); 3791 InvalidateRgn(hwnd, NULL, TRUE);
3783 return ret; 3792 return ret;
3784 } 3793 }
3785 #ifdef AEROGLASS 3794 #ifdef AEROGLASS
3786 case WM_THEMECHANGED: 3795 case WM_THEMECHANGED:
3787 if(_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_SUPPORTED) 3796 if(_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_SUPPORTED)
3788 InvalidateRect(hwnd, NULL, TRUE); 3797 InvalidateRect(hwnd, NULL, TRUE);
3789 break; 3798 break;
3790 #endif 3799 #endif
3791 case WM_PAINT: 3800 case WM_PAINT:
3792 { 3801 {
3811 /* If we are in full dark mode, or we have custom colors selected... 3820 /* If we are in full dark mode, or we have custom colors selected...
3812 * we will draw the status window ourselves... otherwise DrawStatusText() 3821 * we will draw the status window ourselves... otherwise DrawStatusText()
3813 */ 3822 */
3814 if( 3823 if(
3815 #ifdef AEROGLASS 3824 #ifdef AEROGLASS
3816 (_DW_DARK_MODE_ALLOWED == 2 && _DW_DARK_MODE_ENABLED) || 3825 (_DW_DARK_MODE_ALLOWED > 1 && _DW_DARK_MODE_ENABLED) ||
3817 #endif 3826 #endif
3818 (cinfo && cinfo->fore != -1 && cinfo->fore != DW_CLR_DEFAULT && 3827 (cinfo && cinfo->fore != -1 && cinfo->fore != DW_CLR_DEFAULT &&
3819 cinfo->back !=- -1 && cinfo->back != DW_CLR_DEFAULT)) 3828 cinfo->back !=- -1 && cinfo->back != DW_CLR_DEFAULT))
3820 { 3829 {
3821 ULONG fore = (cinfo && (cinfo->fore != -1 && cinfo->fore != DW_CLR_DEFAULT)) ? _internal_color(cinfo->fore) : DW_RGB_TRANSPARENT; 3830 ULONG fore = (cinfo && (cinfo->fore != -1 && cinfo->fore != DW_CLR_DEFAULT)) ? _internal_color(cinfo->fore) : DW_RGB_TRANSPARENT;
13438 #endif 13447 #endif
13439 /* These features are supported and configurable */ 13448 /* These features are supported and configurable */
13440 #ifdef AEROGLASS 13449 #ifdef AEROGLASS
13441 case DW_FEATURE_DARK_MODE: 13450 case DW_FEATURE_DARK_MODE:
13442 { 13451 {
13443 _DW_DARK_MODE_ALLOWED = state; 13452 if(state >= 0 && state <= 4)
13444 return DW_ERROR_NONE; 13453 {
13454 _DW_DARK_MODE_ALLOWED = state;
13455 return DW_ERROR_NONE;
13456 }
13457 return DW_ERROR_GENERAL;
13445 } 13458 }
13446 #endif 13459 #endif
13447 default: 13460 default:
13448 return DW_FEATURE_UNSUPPORTED; 13461 return DW_FEATURE_UNSUPPORTED;
13449 } 13462 }