From: Vince Salvino <salvino@coderedcorp.com>
To: 51404@debbugs.gnu.org
Subject: bug#51404: Support system dark mode on Windows 10
Date: Tue, 26 Oct 2021 04:46:27 +0000 [thread overview]
Message-ID: <CH2PR12MB4231758A937F6FB9F33291CFA5849@CH2PR12MB4231.namprd12.prod.outlook.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 111 bytes --]
Attached is the patch. Additional info available here: https://github.com/vsalvino/emacs
Vince Salvino
[-- Attachment #2: 0001-Support-system-dark-mode-on-Windows-10-version-2004-.patch --]
[-- Type: application/octet-stream, Size: 7491 bytes --]
From 25ec63b9e6dfc411837aa936c06a9a848c690f49 Mon Sep 17 00:00:00 2001
From: Vince Salvino <salvino@coderedcorp.com>
Date: Mon, 25 Oct 2021 22:18:46 -0400
Subject: [PATCH] Support system dark mode on Windows 10 version 2004 and
higher.
---
src/w32.c | 11 +++++--
src/w32.h | 3 ++
src/w32fns.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/src/w32.c b/src/w32.c
index 9fe698d28d..f27c47bba5 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -2822,6 +2822,13 @@ #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
LPBYTE
w32_get_resource (const char *key, LPDWORD lpdwtype)
+{
+ return w32_query_registry(REG_ROOT, key, lpdwtype);
+}
+
+/* Enables reading any key/name from the Windows Registry */
+LPBYTE
+w32_query_registry (const char *root, const char *key, LPDWORD lpdwtype)
{
LPBYTE lpvalue;
HKEY hrootkey = NULL;
@@ -2830,7 +2837,7 @@ w32_get_resource (const char *key, LPDWORD lpdwtype)
/* Check both the current user and the local machine to see if
we have any resources. */
- if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
+ if (RegOpenKeyEx (HKEY_CURRENT_USER, root, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
{
lpvalue = NULL;
@@ -2847,7 +2854,7 @@ w32_get_resource (const char *key, LPDWORD lpdwtype)
RegCloseKey (hrootkey);
}
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, root, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
{
lpvalue = NULL;
diff --git a/src/w32.h b/src/w32.h
index ffa145b148..69468580b4 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -164,6 +164,9 @@ #define FILE_SERIAL 0x0800
/* Return the string resource associated with KEY of type TYPE. */
extern LPBYTE w32_get_resource (const char * key, LPDWORD type);
+/* Utility to query [HKCU|HKLM]\root\key from the Windows Registry */
+extern LPBYTE w32_query_registry (const char * root, const char * key, LPDWORD type);
+
extern void release_listen_threads (void);
extern void init_ntproc (int);
extern void term_ntproc (int);
diff --git a/src/w32fns.c b/src/w32fns.c
index 14d1154a2b..54c03a4a1f 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -73,6 +73,15 @@ #define _WIN32_WINNT 0x0600
#include <imm.h>
#include <windowsx.h>
+/*
+ Internal/undocumented constants for Windows Dark mode.
+ See: https://github.com/microsoft/WindowsAppSDK/issues/41
+*/
+#define DARK_MODE_APP_NAME L"DarkMode_Explorer"
+#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
+#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
+#endif
+
#ifndef FOF_NO_CONNECTED_ELEMENTS
#define FOF_NO_CONNECTED_ELEMENTS 0x2000
#endif
@@ -185,6 +194,11 @@ DECLARE_HANDLE(HMONITOR);
typedef HRESULT (WINAPI *SetThreadDescription_Proc)
(HANDLE hThread, PCWSTR lpThreadDescription);
+typedef HRESULT (WINAPI * SetWindowTheme_Proc)
+ (IN HWND hwnd, IN LPCWSTR pszSubAppName, IN LPCWSTR pszSubIdList);
+typedef HRESULT (WINAPI * DwmSetWindowAttribute_Proc)
+ (HWND hwnd, DWORD dwAttribute, IN LPCVOID pvAttribute, DWORD cbAttribute);
+
TrackMouseEvent_Proc track_mouse_event_fn = NULL;
ImmGetCompositionString_Proc get_composition_string_fn = NULL;
ImmGetContext_Proc get_ime_context_fn = NULL;
@@ -199,6 +213,8 @@ DECLARE_HANDLE(HMONITOR);
GetTitleBarInfo_Proc get_title_bar_info_fn = NULL;
IsDebuggerPresent_Proc is_debugger_present = NULL;
SetThreadDescription_Proc set_thread_description = NULL;
+SetWindowTheme_Proc SetWindowTheme_fn = NULL;
+DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL;
extern AppendMenuW_Proc unicode_append_menu;
@@ -252,6 +268,9 @@ #define MENU_FREE_DELAY 1000
int w32_minor_version;
int w32_build_number;
+/* If the OS is set to use dark mode. */
+BOOL w32_darkmode = FALSE;
+
/* Distinguish between Windows NT and Windows 95. */
int os_subtype;
@@ -2279,10 +2298,31 @@ w32_init_class (HINSTANCE hinst)
}
}
+/* Applies the Windows system theme (light or dark) to a window handle. */
+static void
+w32_applytheme(HWND hwnd)
+{
+ if (w32_darkmode) {
+ /* Set window theme to that of a built-in Windows app (Explorer)
+ because it has dark scroll bars and other UI elements. */
+ if(SetWindowTheme_fn) {
+ SetWindowTheme_fn(hwnd, DARK_MODE_APP_NAME, NULL);
+ }
+ /* Set the titlebar to system dark mode. */
+ if (DwmSetWindowAttribute_fn) {
+ DwmSetWindowAttribute_fn
+ (hwnd,
+ DWMWA_USE_IMMERSIVE_DARK_MODE,
+ &w32_darkmode,
+ sizeof(w32_darkmode));
+ }
+ }
+}
+
static HWND
w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
{
- return CreateWindow ("SCROLLBAR", "",
+ HWND hwnd = CreateWindow ("SCROLLBAR", "",
/* Clip siblings so we don't draw over child
frames. Apparently this is not always
sufficient so we also try to make bar windows
@@ -2291,12 +2331,16 @@ w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
/* Position and size of scroll bar. */
bar->left, bar->top, bar->width, bar->height,
FRAME_W32_WINDOW (f), NULL, hinst, NULL);
+ if(hwnd) {
+ w32_applytheme(hwnd);
+ }
+ return hwnd;
}
static HWND
w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
{
- return CreateWindow ("SCROLLBAR", "",
+ HWND hwnd = CreateWindow ("SCROLLBAR", "",
/* Clip siblings so we don't draw over child
frames. Apparently this is not always
sufficient so we also try to make bar windows
@@ -2305,6 +2349,10 @@ w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
/* Position and size of scroll bar. */
bar->left, bar->top, bar->width, bar->height,
FRAME_W32_WINDOW (f), NULL, hinst, NULL);
+ if(hwnd) {
+ w32_applytheme(hwnd);
+ }
+ return hwnd;
}
static void
@@ -2390,6 +2438,9 @@ w32_createwindow (struct frame *f, int *coords)
/* Enable drag-n-drop. */
DragAcceptFiles (hwnd, TRUE);
+ /* Enable system light/dark theme. */
+ w32_applytheme(hwnd);
+
/* Do this to discard the default setting specified by our parent. */
ShowWindow (hwnd, SW_HIDE);
@@ -11028,6 +11079,32 @@ globals_of_w32fns (void)
set_thread_description = (SetThreadDescription_Proc)
get_proc_addr (hm_kernel32, "SetThreadDescription");
+ /*
+ Support OS dark mode on Windows 10 version 2004 and higher.
+ For future wretches who may need to understand Windows build numbers:
+ https://docs.microsoft.com/en-us/windows/release-health/release-information
+ */
+ if (w32_major_version >= 10 && w32_build_number >= 19041
+ && os_subtype == OS_SUBTYPE_NT) {
+
+ /* Load dwmapi and uxtheme, which will be needed to set window themes. */
+ HMODULE dwmapi_lib = LoadLibrary("dwmapi.dll");
+ DwmSetWindowAttribute_fn = (DwmSetWindowAttribute_Proc)
+ get_proc_addr (dwmapi_lib, "DwmSetWindowAttribute");
+ HMODULE uxtheme_lib = LoadLibrary("uxtheme.dll");
+ SetWindowTheme_fn = (SetWindowTheme_Proc)
+ get_proc_addr (uxtheme_lib, "SetWindowTheme");
+
+ /* Check Windows Registry for system theme. DWORD set to 0 or 1. */
+ LPBYTE val = w32_query_registry
+ ("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
+ "AppsUseLightTheme",
+ NULL);
+ if (val && (DWORD)*val == 0) {
+ w32_darkmode = TRUE;
+ }
+ }
+
except_code = 0;
except_addr = 0;
#ifndef CYGWIN
--
2.33.0.windows.2
next reply other threads:[~2021-10-26 4:46 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-26 4:46 Vince Salvino [this message]
2021-10-26 14:01 ` bug#51404: Support system dark mode on Windows 10 Eli Zaretskii
2021-10-26 16:18 ` Eli Zaretskii
2021-10-26 16:49 ` Vince Salvino
2021-10-26 17:05 ` Eli Zaretskii
2021-10-26 18:20 ` Vince Salvino
2021-10-27 21:41 ` Vince Salvino
2021-10-28 7:15 ` Eli Zaretskii
2021-10-30 10:34 ` Eli Zaretskii
2021-10-30 17:13 ` Vince Salvino
2021-10-30 17:39 ` Eli Zaretskii
2021-11-11 5:36 ` bug#47291: " Lars Ingebrigtsen
2021-11-11 7:51 ` Eli Zaretskii
2021-11-11 12:15 ` Lars Ingebrigtsen
2021-11-11 15:08 ` Eli Zaretskii
2021-11-12 3:00 ` Lars Ingebrigtsen
2021-11-12 6:19 ` Eli Zaretskii
2022-01-14 6:00 ` Vince Salvino
2022-01-23 0:00 ` Vince Salvino
2022-01-29 3:34 ` bug#51404: " Vince Salvino
2022-01-29 8:40 ` bug#51404: " Eli Zaretskii
2022-01-29 20:27 ` Vince Salvino
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CH2PR12MB4231758A937F6FB9F33291CFA5849@CH2PR12MB4231.namprd12.prod.outlook.com \
--to=salvino@coderedcorp.com \
--cc=51404@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).