Browse Source

fix: Windows 7 frame showing for frameless non-resizable windows (#36024)

Co-authored-by: Raymond Zhao <[email protected]>

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Raymond Zhao <[email protected]>
trop[bot] 2 years ago
parent
commit
ec7e24da56

+ 1 - 1
patches/chromium/.patches

@@ -115,10 +115,10 @@ chore_allow_chromium_to_handle_synthetic_mouse_events_for_touch.patch
 add_maximized_parameter_to_linuxui_getwindowframeprovider.patch
 revert_spellcheck_fully_launch_spell_check_delayed_initialization.patch
 add_electron_deps_to_license_credits_file.patch
-feat_add_set_can_resize_mutator.patch
 fix_crash_loading_non-standard_schemes_in_iframes.patch
 disable_optimization_guide_for_preconnect_feature.patch
 fix_return_v8_value_from_localframe_requestexecutescript.patch
 create_browser_v8_snapshot_file_name_fuse.patch
 cherry-pick-c83640db21b5.patch
 fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch
+fix_remove_caption-removing_style_call.patch

+ 0 - 27
patches/chromium/feat_add_set_can_resize_mutator.patch

@@ -1,27 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Raymond Zhao <[email protected]>
-Date: Tue, 2 Aug 2022 09:30:36 -0700
-Subject: feat: Add set_can_resize mutator
-
-Adds a set_can_resize mutator to WidgetDelegate that
-doesn't emit the OnSizeConstraintsChanged event.
-This way, we can call set_can_resize from Electron before
-the widget is initialized to set the value earlier,
-and in turn, avoid showing a frame at startup
-for frameless applications.
-
-diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h
-index 8e15368a19ec68a468ad9834dd6d08b5b30f98a8..9b73c9faf0fa25568d0a278b1e9a1933ba20224f 100644
---- a/ui/views/widget/widget_delegate.h
-+++ b/ui/views/widget/widget_delegate.h
-@@ -323,6 +323,10 @@ class VIEWS_EXPORT WidgetDelegate {
-   // be cycled through with keyboard focus.
-   virtual void GetAccessiblePanes(std::vector<View*>* panes) {}
- 
-+  // A setter for the can_resize parameter that doesn't
-+  // emit any events.
-+  void set_can_resize(bool can_resize) { params_.can_resize = can_resize; }
-+
-   // Setters for data parameters of the WidgetDelegate. If you use these
-   // setters, there is no need to override the corresponding virtual getters.
-   void SetAccessibleRole(ax::mojom::Role role);

+ 48 - 0
patches/chromium/fix_remove_caption-removing_style_call.patch

@@ -0,0 +1,48 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Raymond Zhao <[email protected]>
+Date: Wed, 17 Aug 2022 13:49:40 -0700
+Subject: fix: Adjust caption-removing style call
+
+There is a SetWindowLong call that removes WS_CAPTION for frameless
+windows, but Electron uses WS_CAPTION even for frameless windows,
+unless they are transparent.
+
+Changing this call only affects frameless windows, and it fixes
+a visual glitch where they showed a Windows 7 style frame
+during startup.
+
+The if statement was originally introduced by
+https://codereview.chromium.org/9372053/, and it was there to fix
+a visual glitch with the close button showing up during startup
+or resizing, but Electron does not seem to run into that issue
+for opaque frameless windows even with that block commented out.
+
+diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
+index 400278ab26a4e095fd837fcf84c952a1297b173d..55afa69870f27b877826ea8a442ab20a8b336d74 100644
+--- a/ui/views/win/hwnd_message_handler.cc
++++ b/ui/views/win/hwnd_message_handler.cc
+@@ -1731,7 +1731,23 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
+   SendMessage(hwnd(), WM_CHANGEUISTATE, MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS),
+               0);
+ 
+-  if (!delegate_->HasFrame()) {
++  LONG is_popup =
++      GetWindowLong(hwnd(), GWL_STYLE) & static_cast<LONG>(WS_POPUP);
++
++  // For transparent windows, Electron removes the WS_CAPTION style,
++  // so we continue to remove it here. If we didn't, an opaque rectangle
++  // would show up.
++  // For non-transparent windows, Electron keeps the WS_CAPTION style,
++  // so we don't remove it in that case. If we did, a Windows 7 frame
++  // would show up.
++  // We also need this block for frameless popup windows. When the user opens
++  // a dropdown in an Electron app, the internal popup menu from
++  // third_party/blink/renderer/core/html/forms/internal_popup_menu.h
++  // is rendered. That menu is actually an HTML page inside of a frameless popup window.
++  // A new popup window is created every time the user opens the dropdown,
++  // and this code path is run. The code block below runs SendFrameChanged,
++  // which gives the dropdown options the proper layout.
++  if (!delegate_->HasFrame() && (is_translucent_ || is_popup)) {
+     SetWindowLong(hwnd(), GWL_STYLE,
+                   GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION);
+     SendFrameChanged();

+ 0 - 17
shell/browser/native_window_views.cc

@@ -281,24 +281,7 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
       new ElectronDesktopWindowTreeHostLinux(this, native_widget);
 #endif
 
-  // Ref https://github.com/electron/electron/issues/30760
-  // Set the can_resize param before initializing the widget.
-  // When resizable_ is true, this causes the WS_THICKFRAME style
-  // to be passed into CreateWindowEx and SetWindowLong calls in
-  // WindowImpl::Init and HwndMessageHandler::SizeConstraintsChanged
-  // respectively. As a result, the Windows 7 frame doesn't show,
-  // but it isn't clear why this is the case.
-  // When resizable_ is false, WS_THICKFRAME is not passed into the
-  // SetWindowLong call, so the Windows 7 frame still shows.
-  // One workaround would be to call set_can_resize(true) here,
-  // and then move the SetCanResize(resizable_) call after the
-  // SetWindowLong call around line 365, but that's a much larger change.
-  set_can_resize(true);
   widget()->Init(std::move(params));
-
-  // When the workaround above is not needed anymore, only this
-  // call should be necessary.
-  // With the workaround in place, this call doesn't do anything.
   SetCanResize(resizable_);
 
   bool fullscreen = false;