Repository: electron/electron (language: cpp)

Issue:
[Bug]: set "transparent" to true and "titleBarStyle” to "hidden", a title bar is shown when window loses focus, "backgroundMaterial" not work until resizing the window.
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

27.0.0-beta.5

### What operating system are you using?

Windows

### Operating System Version

Windows 11 - 22H2 

### What arch are you using?

x64

### Last Known Working Electron version

_No response_

### Expected Behavior

1、The window should show without a title bar.
2、The window should be transparent and backgrounds should be "acrylic" style.
![image](https://github.com/electron/electron/assets/13523898/42e404c0-7215-4810-9603-06d93e0b95ad)



### Actual Behavior

1、window background not transparent and not "acrylic" style until I resize the window.

![image](https://github.com/electron/electron/assets/13523898/13e58cf2-4695-4d60-8cf1-f6d347febdf0)
 after resize the window:
![image](https://github.com/electron/electron/assets/13523898/87c3ed1a-0858-4812-a5f5-857034d9e6b3)


2、If the window loses focus, a title bar is shown and it can't interact.

![image](https://github.com/electron/electron/assets/13523898/2a733fde-4f60-4947-9891-97f18073890d)


### Testcase Gist URL

https://gist.github.com/d51806da56e0f6103859d0164b22a80a

### Additional Information

_No response_


Discussion / hints:
Confirmed in the environment (Electron 27.0.0-beta.5, Windows 11 - 22H2). Can be divided into two independent issues:
1. Transparent window without frame (`frame: false, transparent: true` or `transparent: true, titleBarStyle: 'hidden'`) shows the title bar when it loses focus.
2. Transparent window without frame still doesn't work with Mica, resizing the window solves the problem (however when I hide/show the window it stops working again).
cc @clavin 
The phantom titlebar that is drawn under everything seems to happen even without acrylic (transparent true, frame false and/or titleBarStyle hidden).

But there seem to be a whole collection of bugs around these handful of settings that need to be tackled at the same time, this feel like whack-a-mole otherwise. I think they're all related to window flags that overlap each other.

Something is drawing a phantom titlebar which can be seen when titleBarStyle=hidden and transparent=true
Something is not setting up the window correctly on initial show wrt acrylic
With frame on but titlebar hidden, the Windows 11 rounded corners are lost
If transparent=true the window is no longer resizeable unless you set titleBarStyle=hidden

(Also, some combinations of the settings may not be possible? I feel the documentation should be updated.)

With all of these issues, there's no way to make a Windows 11 style app which should have rounded corners, no oldstyle titlebar, and parts or all of the content being acrylic/mica.
Any updates on this? We finally got #40062 solved (but not merged with 26), and now this is blocking us from upgrading to 27 😭. We're stuck on 25 with a horrible bug where sharing screen during a call will crash the full app randomly.

@clavin let us know if there's any way we can support you in testing or being guinea pigs. cc. @VerteDinde 

Much gratitude, as always, for supporting this project 🙏 
As a workaround, set the background as `#00000000` when the window is foucsed or blurred can hide the title bar

```javascript
win.on('blur', () => {
  win.setBackgroundColor('#00000000')
})

win.on('focus', () => {
  win.setBackgroundColor('#00000000')
})
```
Thanks @KochiyaOcean! And along those lines, putting this in the focus handler kicks the acrylic into action (although does give you a flicker in dev mode):
```
const [w, h] = win.getSize();
win.setSize(w, h);
```
Now, how to fix rounded corners...?

Or should I just carry on using the Win10-era native hacks in [electron-acrylic-window](https://www.npmjs.com/package/electron-acrylic-window)?
> Thanks @KochiyaOcean! And along those lines, putting this in the focus handler kicks the acrylic into action (although does give you a flicker in dev mode):
> 
> ```
> const [w, h] = win.getSize();
> win.setSize(w, h);
> ```
> 
> Now, how to fix rounded corners...?
> 
> Or should I just carry on using the Win10-era native hacks in [electron-acrylic-window](https://www.npmjs.com/package/electron-acrylic-window)?

I think the only way is to wait until dev fix it, I've tried some ways but cannot bring round corner back
It seems like the real problem is when you use showInactive instead of show(). Keep the same settings without the mentioned workarounds and use show() instead and see the issue is gone. I know that show() behaves different, just giving more insights so the fix comes faster!
@codebytere FYI
Hello! Our team faced the same issue after upgrading electron to the 27 version.
We can provide you with another reproduction if needed.
Unfortunately, @KochiyaOcean's workaround didn't work for us  :( 

Could you update us on the progress of the bug?




### Some information about our case, we hope it would help you
#### **Electron Version**
"electron": "~27.0.0"
#### **What operating system are you using?**
Windows
#### **Operating System Version**
Windows 10/11
#### **What arch are you using?**
x64
#### **Last Known Working Electron version**
`"electron": "~25.8.0"


@clavin FYI
This issue looks the same as #40285
I have the same issue with Electron 27.0.2.

Impossible to get rid of that phantom titlebar.

(transparent: true and titleBarStyle: 'hidden')
As I mentioned in another issue,  the reason is that when transparent is true, the thick frame will be disabled, which causes phantom title bar.

https://github.com/electron/electron/blob/652f995128de858c7a68fad853f56e80e0c2c222/shell/browser/native_window_views.cc#L238-L241

I've opened a PR to allow thickFrame transparent window, but since it's taking breaking changes, I'm wondering if there is a better way to fix it
The title bar issue is caused by `WN_NCACTIVATE` messages being sent to frameless transparent windows, see #40395 for more details
+1 can reproduce, have repo with sample app if needed
We stumbled across the issue with the title bar appearing after removing this line on the transparent window: `window.setContentProtection(true)`. When adding that line back, the title bar no longer appeared.

So, at least for us, it seems that setting content protection to `true` is a temporary workaround to prevent the title bar from appearing. We're on `electron@27.0.3`.
after resize the window is ok .

I dynamically adjust the window size when the window loses focus and regains focus. is work for me.
+1
+1
I also have this issue when a transparent and frameless window loses focus for the first time. 

Fix patch:
diff --git a/patches/chromium/fix_activate_background_material_on_windows.patch b/patches/chromium/fix_activate_background_material_on_windows.patch
index d63c73f064977..06e2c436362bf 100644
--- a/patches/chromium/fix_activate_background_material_on_windows.patch
+++ b/patches/chromium/fix_activate_background_material_on_windows.patch
@@ -1,19 +1,23 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: clavin <clavin@electronjs.org>
-Date: Wed, 30 Aug 2023 18:15:36 -0700
+Date: Mon, 11 Dec 2023 20:43:34 -0300
 Subject: fix: activate background material on windows
 
 This patch adds a condition to the HWND message handler to allow windows
 with translucent background materials to become activated.
 
+It also ensures the lParam of WM_NCACTIVATE is set to -1 so as to not repaint
+the client area, which can lead to a title bar incorrectly being displayed in
+frameless windows.
+
 This patch likely can't be upstreamed as-is, as Chromium doesn't have
 this use case in mind currently.
 
 diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
-index 23905a6b7f739ff3c6f391f984527ef5d2ed0bd9..ee72bad1b884677b02cc2f86ea307742e5528bad 100644
+index 23905a6b7f739ff3c6f391f984527ef5d2ed0bd9..aed8894a5514fddfc8d15b8fb4ae611fa4493b6f 100644
 --- a/ui/views/win/hwnd_message_handler.cc
 +++ b/ui/views/win/hwnd_message_handler.cc
-@@ -901,7 +901,7 @@ void HWNDMessageHandler::FrameTypeChanged() {
+@@ -901,13 +901,13 @@ void HWNDMessageHandler::FrameTypeChanged() {
  
  void HWNDMessageHandler::PaintAsActiveChanged() {
    if (!delegate_->HasNonClientView() || !delegate_->CanActivate() ||
@@ -22,3 +26,34 @@ index 23905a6b7f739ff3c6f391f984527ef5d2ed0bd9..ee72bad1b884677b02cc2f86ea307742
        (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN)) {
      return;
    }
+ 
+   DefWindowProcWithRedrawLock(WM_NCACTIVATE, delegate_->ShouldPaintAsActive(),
+-                              0);
++                              delegate_->HasFrame() ? 0 : -1);
+ }
+ 
+ void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon,
+@@ -2254,17 +2254,18 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message,
+   if (IsVisible())
+     delegate_->SchedulePaint();
+ 
+-  // Calling DefWindowProc is only necessary if there's a system frame being
+-  // drawn. Otherwise it can draw an incorrect title bar and cause visual
+-  // corruption.
+-  if (!delegate_->HasFrame() ||
++  // If the window is translucent, it may have the Mica background.
++  // In that case, it's necessary to call |DefWindowProc|, but we can
++  // pass -1 in the lParam to prevent any non-client area elements from
++  // being displayed.
++  if ((!delegate_->HasFrame() && !is_translucent_) ||
+       delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
+     SetMsgHandled(TRUE);
+     return TRUE;
+   }
+ 
+   return DefWindowProcWithRedrawLock(WM_NCACTIVATE, paint_as_active || active,
+-                                     0);
++                                     delegate_->HasFrame() ? 0 : -1);
+ }
+ 
+ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
diff --git a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc
index d60675f31feab..e9dab479abe19 100644
--- a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc
+++ b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc
@@ -135,12 +135,12 @@ void ElectronDesktopWindowTreeHostWin::OnNativeThemeUpdated(
 
 bool ElectronDesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent()
     const {
-  // Window should be marked as opaque if no transparency setting has been set,
-  // otherwise videos rendered in the window will trigger a DirectComposition
-  // redraw for every frame.
+  // Window should be marked as opaque if no transparency setting has been
+  // set, otherwise animations or videos rendered in the window will trigger a
+  // DirectComposition redraw for every frame.
   // https://github.com/electron/electron/pull/39895
   return native_window_view_->GetOpacity() < 1.0 ||
-         native_window_view_->transparent();
+         native_window_view_->IsTranslucent();
 }
 
 }  // namespace electron


Test patch: