diff --git a/browser/app/firefox.exe.manifest b/browser/app/firefox.exe.manifest
index 1e1d6f651d27..995b2fc869c1 100644
--- a/browser/app/firefox.exe.manifest
+++ b/browser/app/firefox.exe.manifest
@@ -36,12 +36,6 @@
-
-
- True/PM
- PerMonitorV2,PerMonitor
-
-
diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp
index 12ed20d3b00d..a755eeab080b 100644
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -28,6 +28,7 @@
# include "freestanding/SharedSection.h"
# include "LauncherProcessWin.h"
# include "mozilla/WindowsDllBlocklist.h"
+# include "mozilla/WindowsDpiInitialization.h"
# define XRE_WANT_ENVIRON
# define strcasecmp _stricmp
@@ -296,6 +297,19 @@ int main(int argc, char* argv[], char* envp[]) {
DllBlocklist_Initialize(gBlocklistInitFlags |
eDllBlocklistInitFlagIsChildProcess);
# endif
+# if defined(XP_WIN)
+ // Ideally, we would be able to set our DPI awareness in
+ // firefox.exe.manifest Unfortunately, that would cause Win32k calls when
+ // user32.dll gets loaded, which would be incompatible with Win32k Lockdown
+ //
+ // MSDN says that it's allowed-but-not-recommended to initialize DPI
+ // programatically, as long as it's done before any HWNDs are created.
+ // Thus, we do it almost as soon as we possibly can
+ {
+ auto result = mozilla::WindowsDpiInitialization();
+ (void)result; // Ignore errors since some tools block DPI calls
+ }
+# endif
# if defined(XP_WIN) && defined(MOZ_SANDBOX)
// We need to initialize the sandbox TargetServices before InitXPCOMGlue
// because we might need the sandbox broker to give access to some files.
@@ -328,6 +342,19 @@ int main(int argc, char* argv[], char* envp[]) {
#endif
#if defined(XP_WIN)
+
+ // Ideally, we would be able to set our DPI awareness in firefox.exe.manifest
+ // Unfortunately, that would cause Win32k calls when user32.dll gets loaded,
+ // which would be incompatible with Win32k Lockdown
+ //
+ // MSDN says that it's allowed-but-not-recommended to initialize DPI
+ // programatically, as long as it's done before any HWNDs are created.
+ // Thus, we do it almost as soon as we possibly can
+ {
+ auto result = mozilla::WindowsDpiInitialization();
+ (void)result; // Ignore errors since some tools block DPI calls
+ }
+
// Once the browser process hits the main function, we no longer need
// a writable section handle because all dependent modules have been
// loaded.
diff --git a/mozglue/misc/WindowsDpiInitialization.cpp b/mozglue/misc/WindowsDpiInitialization.cpp
new file mode 100644
index 000000000000..2e957b583012
--- /dev/null
+++ b/mozglue/misc/WindowsDpiInitialization.cpp
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/WindowsDpiInitialization.h"
+
+#include "mozilla/DynamicallyLinkedFunctionPtr.h"
+#include "mozilla/WindowsProcessMitigations.h"
+#include "mozilla/WindowsVersion.h"
+
+#include
+#include
+
+namespace mozilla {
+
+typedef HRESULT(WINAPI* SetProcessDpiAwarenessType)(PROCESS_DPI_AWARENESS);
+typedef BOOL(WINAPI* SetProcessDpiAwarenessContextType)(DPI_AWARENESS_CONTEXT);
+
+WindowsDpiInitializationResult WindowsDpiInitialization() {
+ // DPI Awareness can't be used in a Win32k Lockdown process, so there's
+ // nothing to do
+ if (IsWin32kLockedDown()) {
+ return WindowsDpiInitializationResult::Success;
+ }
+
+ // From MSDN:
+ // SetProcessDpiAwarenessContext() was added in the Win10 Anniversary Update
+ // SetProcessDpiAwareness() was added in Windows 8.1
+ // SetProcessDpiAware() was added in Windows Vista
+ //
+ // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 wasn't added later until
+ // the Creators Update, so if it fails we just fall back to
+ // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
+ if (IsWin10AnniversaryUpdateOrLater()) {
+ DynamicallyLinkedFunctionPtr
+ setProcessDpiAwarenessContext(L"user32.dll",
+ "SetProcessDpiAwarenessContext");
+ if (!setProcessDpiAwarenessContext) {
+ return WindowsDpiInitializationResult::
+ FindSetProcessDpiAwarenessContextFailed;
+ }
+
+ if (!setProcessDpiAwarenessContext(
+ DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) &&
+ !setProcessDpiAwarenessContext(
+ DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
+ return WindowsDpiInitializationResult::
+ SetProcessDpiAwarenessContextFailed;
+ }
+
+ return WindowsDpiInitializationResult::Success;
+ } else if (IsWin8Point1OrLater()) {
+ DynamicallyLinkedFunctionPtr
+ setProcessDpiAwareness(L"Shcore.dll", "SetProcessDpiAwareness");
+ if (!setProcessDpiAwareness) {
+ return WindowsDpiInitializationResult::FindSetProcessDpiAwarenessFailed;
+ }
+
+ if (FAILED(setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE))) {
+ return WindowsDpiInitializationResult::SetProcessDpiAwarenessFailed;
+ }
+
+ return WindowsDpiInitializationResult::Success;
+ } else {
+ if (!SetProcessDPIAware()) {
+ return WindowsDpiInitializationResult::SetProcessDPIAwareFailed;
+ }
+
+ return WindowsDpiInitializationResult::Success;
+ }
+}
+
+} // namespace mozilla
diff --git a/mozglue/misc/WindowsDpiInitialization.h b/mozglue/misc/WindowsDpiInitialization.h
new file mode 100644
index 000000000000..5943d50526e3
--- /dev/null
+++ b/mozglue/misc/WindowsDpiInitialization.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_MOZGLUE_MISC_WINDOWSDPIINITIALIZATION_H_
+#define MOZILLA_MOZGLUE_MISC_WINDOWSDPIINITIALIZATION_H_
+#include "mozilla/Types.h"
+
+namespace mozilla {
+
+// The result codes that may be returned from WindowsDpiInitialization()
+enum class WindowsDpiInitializationResult : uint32_t {
+ Success,
+ FindSetProcessDpiAwarenessContextFailed,
+ SetProcessDpiAwarenessContextFailed,
+ FindSetProcessDpiAwarenessFailed,
+ SetProcessDpiAwarenessFailed,
+ SetProcessDPIAwareFailed,
+};
+
+// Get a string representation of any WindowsDpiInitializationResult value
+inline const char* WindowsDpiInitializationResultString(
+ WindowsDpiInitializationResult result) {
+ switch (result) {
+ case WindowsDpiInitializationResult::Success:
+ return "Success";
+ case WindowsDpiInitializationResult::
+ FindSetProcessDpiAwarenessContextFailed:
+ return "Failed to find SetProcessDpiAwarenessContext";
+ case WindowsDpiInitializationResult::SetProcessDpiAwarenessContextFailed:
+ return "SetProcessDpiAwarenessContext failed";
+ case WindowsDpiInitializationResult::FindSetProcessDpiAwarenessFailed:
+ return "Failed to find SetProcessDpiAwareness";
+ case WindowsDpiInitializationResult::SetProcessDpiAwarenessFailed:
+ return "SetProcessDpiAwareness failed";
+ case WindowsDpiInitializationResult::SetProcessDPIAwareFailed:
+ return "SetProcessDPIAware failed";
+ default:
+ return "Unknown result";
+ }
+}
+
+// Initialize DPI awareness to the best available for the current OS
+// According to MSDN, this will be:
+// Per-Monitor V2 for Windows 10 Creators Update (1703) and later
+// Per-Monitor V1 for Windows 8.1 and later
+// System DPI for Vista and later (we don't support anything older)
+// https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
+MFBT_API WindowsDpiInitializationResult WindowsDpiInitialization();
+
+} // namespace mozilla
+
+#endif // MOZILLA_MOZGLUE_MISC_WINDOWSDPIINITIALIZATION_H_
diff --git a/mozglue/misc/moz.build b/mozglue/misc/moz.build
index 45c2a7773ecf..36e472d6918a 100644
--- a/mozglue/misc/moz.build
+++ b/mozglue/misc/moz.build
@@ -59,6 +59,7 @@ if CONFIG["OS_ARCH"] == "WINNT":
"DynamicallyLinkedFunctionPtr.h",
"ImportDir.h",
"NativeNt.h",
+ "WindowsDpiInitialization.h",
"WindowsEnumProcessModules.h",
"WindowsMapRemoteView.h",
"WindowsProcessMitigations.h",
@@ -69,6 +70,7 @@ if CONFIG["OS_ARCH"] == "WINNT":
SOURCES += [
"PreXULSkeletonUI.cpp",
"TimeStamp_windows.cpp",
+ "WindowsDpiInitialization.cpp",
"WindowsMapRemoteView.cpp",
"WindowsProcessMitigations.cpp",
"WindowsUnicode.cpp",