Browse Source

fix: initial dark mode title bar on Windows 10 (#39287)

David Sanders 1 year ago
parent
commit
b2c62d6ad1

+ 29 - 1
shell/browser/ui/win/electron_desktop_window_tree_host_win.cc

@@ -8,6 +8,7 @@
 #include "electron/buildflags/buildflags.h"
 #include "shell/browser/ui/views/win_frame_view.h"
 #include "shell/browser/win/dark_mode.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/win/hwnd_metrics.h"
 #include "ui/base/win/shell.h"
 
@@ -37,6 +38,14 @@ bool ElectronDesktopWindowTreeHostWin::PreHandleMSG(UINT message,
   return native_window_view_->PreHandleMSG(message, w_param, l_param, result);
 }
 
+bool ElectronDesktopWindowTreeHostWin::ShouldPaintAsActive() const {
+  if (force_should_paint_as_active_.has_value()) {
+    return force_should_paint_as_active_.value();
+  }
+
+  return views::DesktopWindowTreeHostWin::ShouldPaintAsActive();
+}
+
 bool ElectronDesktopWindowTreeHostWin::GetDwmFrameInsetsInPixels(
     gfx::Insets* insets) const {
   // Set DWMFrameInsets to prevent maximized frameless window from bleeding
@@ -102,7 +111,26 @@ bool ElectronDesktopWindowTreeHostWin::HandleMouseEventForCaption(
 
 void ElectronDesktopWindowTreeHostWin::OnNativeThemeUpdated(
     ui::NativeTheme* observed_theme) {
-  win::SetDarkModeForWindow(GetAcceleratedWidget());
+  HWND hWnd = GetAcceleratedWidget();
+  win::SetDarkModeForWindow(hWnd);
+
+  auto* os_info = base::win::OSInfo::GetInstance();
+  auto const version = os_info->version();
+
+  // Toggle the nonclient area active state to force a redraw (Win10 workaround)
+  if (version < base::win::Version::WIN11) {
+    // When handling WM_NCACTIVATE messages, Chromium logical ORs the wParam and
+    // the value of ShouldPaintAsActive() - so if the latter is true, it's not
+    // possible to toggle the title bar to inactive. Force it to false while we
+    // send the message so that the wParam value will always take effect. Refs
+    // https://source.chromium.org/chromium/chromium/src/+/main:ui/views/win/hwnd_message_handler.cc;l=2332-2381;drc=e6361d070be0adc585ebbff89fec76e2df4ad768
+    force_should_paint_as_active_ = false;
+    ::SendMessage(hWnd, WM_NCACTIVATE, hWnd != ::GetActiveWindow(), 0);
+
+    // Clear forced value and tell Chromium the value changed to get a repaint
+    force_should_paint_as_active_.reset();
+    PaintAsActiveChanged();
+  }
 }
 
 }  // namespace electron

+ 3 - 0
shell/browser/ui/win/electron_desktop_window_tree_host_win.h

@@ -8,6 +8,7 @@
 #include <windows.h>
 
 #include "shell/browser/native_window_views.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
 
 namespace electron {
@@ -31,6 +32,7 @@ class ElectronDesktopWindowTreeHostWin : public views::DesktopWindowTreeHostWin,
                     WPARAM w_param,
                     LPARAM l_param,
                     LRESULT* result) override;
+  bool ShouldPaintAsActive() const override;
   bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override;
   bool GetClientAreaInsets(gfx::Insets* insets,
                            HMONITOR monitor) const override;
@@ -41,6 +43,7 @@ class ElectronDesktopWindowTreeHostWin : public views::DesktopWindowTreeHostWin,
 
  private:
   raw_ptr<NativeWindowViews> native_window_view_;  // weak ref
+  absl::optional<bool> force_should_paint_as_active_;
 };
 
 }  // namespace electron

+ 0 - 10
shell/browser/win/dark_mode.cc

@@ -25,16 +25,6 @@ HRESULT TrySetWindowTheme(HWND hWnd, bool dark) {
   if (FAILED(result))
     return result;
 
-  auto* os_info = base::win::OSInfo::GetInstance();
-  auto const version = os_info->version();
-
-  // Toggle the nonclient area active state to force a redraw (Win10 workaround)
-  if (version < base::win::Version::WIN11) {
-    HWND activeWindow = GetActiveWindow();
-    SendMessage(hWnd, WM_NCACTIVATE, hWnd != activeWindow, 0);
-    SendMessage(hWnd, WM_NCACTIVATE, hWnd == activeWindow, 0);
-  }
-
   return S_OK;
 }