electron_desktop_window_tree_host_win.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright (c) 2015 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/ui/win/electron_desktop_window_tree_host_win.h"
  5. #include "base/win/windows_version.h"
  6. #include "electron/buildflags/buildflags.h"
  7. #include "shell/browser/ui/views/win_frame_view.h"
  8. #include "shell/browser/win/dark_mode.h"
  9. #include "ui/base/win/hwnd_metrics.h"
  10. #include "ui/base/win/shell.h"
  11. namespace electron {
  12. ElectronDesktopWindowTreeHostWin::ElectronDesktopWindowTreeHostWin(
  13. NativeWindowViews* native_window_view,
  14. views::DesktopNativeWidgetAura* desktop_native_widget_aura)
  15. : views::DesktopWindowTreeHostWin(native_window_view->widget(),
  16. desktop_native_widget_aura),
  17. native_window_view_(native_window_view) {}
  18. ElectronDesktopWindowTreeHostWin::~ElectronDesktopWindowTreeHostWin() = default;
  19. bool ElectronDesktopWindowTreeHostWin::PreHandleMSG(UINT message,
  20. WPARAM w_param,
  21. LPARAM l_param,
  22. LRESULT* result) {
  23. const bool dark_mode_supported = win::IsDarkModeSupported();
  24. if (dark_mode_supported && message == WM_NCCREATE) {
  25. win::SetDarkModeForWindow(GetAcceleratedWidget());
  26. ui::NativeTheme::GetInstanceForNativeUi()->AddObserver(this);
  27. } else if (dark_mode_supported && message == WM_DESTROY) {
  28. ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
  29. }
  30. return native_window_view_->PreHandleMSG(message, w_param, l_param, result);
  31. }
  32. bool ElectronDesktopWindowTreeHostWin::ShouldPaintAsActive() const {
  33. // Tell Chromium to use system default behavior when rendering inactive
  34. // titlebar, otherwise it would render inactive titlebar as active under
  35. // some cases.
  36. // See also https://github.com/electron/electron/issues/24647.
  37. return false;
  38. }
  39. bool ElectronDesktopWindowTreeHostWin::HasNativeFrame() const {
  40. // Since we never use chromium's titlebar implementation, we can just say
  41. // that we use a native titlebar. This will disable the repaint locking when
  42. // DWM composition is disabled.
  43. // See also https://github.com/electron/electron/issues/1821.
  44. return !ui::win::IsAeroGlassEnabled();
  45. }
  46. bool ElectronDesktopWindowTreeHostWin::GetDwmFrameInsetsInPixels(
  47. gfx::Insets* insets) const {
  48. // Set DWMFrameInsets to prevent maximized frameless window from bleeding
  49. // into other monitors.
  50. if (IsMaximized() && !native_window_view_->has_frame()) {
  51. // This would be equivalent to calling:
  52. // DwmExtendFrameIntoClientArea({0, 0, 0, 0});
  53. //
  54. // which means do not extend window frame into client area. It is almost
  55. // a no-op, but it can tell Windows to not extend the window frame to be
  56. // larger than current workspace.
  57. //
  58. // See also:
  59. // https://devblogs.microsoft.com/oldnewthing/20150304-00/?p=44543
  60. *insets = gfx::Insets();
  61. return true;
  62. }
  63. return false;
  64. }
  65. bool ElectronDesktopWindowTreeHostWin::GetClientAreaInsets(
  66. gfx::Insets* insets,
  67. HMONITOR monitor) const {
  68. // Windows by default extends the maximized window slightly larger than
  69. // current workspace, for frameless window since the standard frame has been
  70. // removed, the client area would then be drew outside current workspace.
  71. //
  72. // Indenting the client area can fix this behavior.
  73. if (IsMaximized() && !native_window_view_->has_frame()) {
  74. // The insets would be eventually passed to WM_NCCALCSIZE, which takes
  75. // the metrics under the DPI of _main_ monitor instead of current monitor.
  76. //
  77. // Please make sure you tested maximized frameless window under multiple
  78. // monitors with different DPIs before changing this code.
  79. const int thickness = ::GetSystemMetrics(SM_CXSIZEFRAME) +
  80. ::GetSystemMetrics(SM_CXPADDEDBORDER);
  81. *insets = gfx::Insets::TLBR(thickness, thickness, thickness, thickness);
  82. return true;
  83. }
  84. return false;
  85. }
  86. void ElectronDesktopWindowTreeHostWin::OnNativeThemeUpdated(
  87. ui::NativeTheme* observed_theme) {
  88. win::SetDarkModeForWindow(GetAcceleratedWidget());
  89. }
  90. } // namespace electron