Repository: electron/electron
Pull request: fix: setTopBrowserView focus issue with reordering

#### Description of Change
fixes: https://github.com/electron/electron/issues/42637

### Summary of bug
- As highlighted in the [issue](https://github.com/electron/electron/issues/42637), prior to v30, when setting a view to `setTopBrowserView`, the view would focus correctly, and that is because it's using the [macOS view ordering APIs](https://github.com/electron/electron/commit/15c60143241c7d0335f3bc8c722054ce6b8a9481#diff-f9d7ef71aadb519c42f18e9c0170137f634f267d72036ab62c3c9e4548c266e0L1404) to reorder the view to the top without reseting any state.
- With the new WebContentView changes in v30, we updated our implementation of `setTopBrowserView` to:
```
BrowserWindow.prototype.setTopBrowserView = function (browserView: BrowserView) {
  if (browserView.ownerWindow !== this) { throw new Error('Given BrowserView is not attached to the window'); }
   this.addBrowserView(browserView);
};
```
The issue arises because `this.addBrowserView` removes the view from the owner window before re-adding it. This removal [removes the view from the focus list](https://source.chromium.org/chromium/chromium/src/+/main:ui/views/view.cc;l=3054;bpv=0;bpt=1) and resets its state, causing the top view to incorrectly focus.


### Proposed fix

-  [This PR](https://github.com/electron/electron/pull/42085) has already added Chromium's [reordering API ](https://github.com/electron/electron/pull/42085/files#diff-ffd5b94a3537909d007f9eee80f2d4b97d56129965fed44226f50c4aad6e5773R227) inside `AddChildViewAt` to reorder if  the child is already a child of this view. So calling `this.contentView.addChildView` directly on a view that already exists on the window will reorder it to the top. 
- Tested with my local build of electron and works as expected

<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [x] relevant documentation, tutorials, templates and examples are changed or added
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Fixed a focus issue when calling `BrowserWindow.setTopBrowserView` 


Changed files:
filename: lib/browser/api/browser-window.ts
patch: @@ -232,7 +232,12 @@ BrowserWindow.prototype.getBrowserViews = function () {
 
 BrowserWindow.prototype.setTopBrowserView = function (browserView: BrowserView) {
   if (browserView.ownerWindow !== this) { throw new Error('Given BrowserView is not attached to the window'); }
-  this.addBrowserView(browserView);
+  const idx = this._browserViews.indexOf(browserView);
+  if (idx >= 0) {
+    this.contentView.addChildView(browserView.webContentsView);
+    this._browserViews.splice(idx, 1);
+    this._browserViews.push(browserView);
+  }
 };
 
 module.exports = BrowserWindow;

filename: spec/api-browser-view-spec.ts
patch: @@ -520,6 +520,19 @@ describe('BrowserView module', () => {
       win2.close();
       win2.destroy();
     });
+
+    it('should reorder the BrowserView to the top if it is already in the window', () => {
+      view = new BrowserView();
+      const view2 = new BrowserView();
+      defer(() => view2.webContents.destroy());
+      w.addBrowserView(view);
+      w.addBrowserView(view2);
+      defer(() => w.removeBrowserView(view2));
+
+      w.setTopBrowserView(view);
+      const views = w.getBrowserViews();
+      expect(views.indexOf(view)).to.equal(views.length - 1);
+    });
   });
 
   describe('BrowserView.webContents.getOwnerBrowserWindow()', () => {