Repository: electron
Issue: [Feature Request]: Extend the functionality of the `getAllWindows` function.
Labels: stale

### 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 feature request that matches the one I want to file, without success.

### Problem Description

When developing multi-window applications, it is not easy to obtain specific windows. Although windows have an `id` property, this `id` is not fixed; it is generated based on the order in which windows are opened, and the `id` is not released when a window is closed. In a modular development scenario, exporting and importing windows can lead to a messy relationship (confusing: the next time you need to import a specific window, you have to search for the module file, and I may not remember where it is!). Without exporting windows, the only methods available are `getFocusedWindow` and `getAllWindows`, both of which still have limitations.

### Proposed Solution

Extend the `getAllWindows` method:
Add a `name` property to the `option` parameter of `new BrowserWindow(option)`. This `name` acts similarly to the `class` attribute in HTML tags, allowing it to be retrieved by the `getAllWindows` method. For example:

```javascript
const windowA = new BrowserWindow({ width: 800, height: 600, name: 'a' });
const windowB = new BrowserWindow({ width: 800, height: 600, name: 'b' });
const windowC = new BrowserWindow({ width: 200, height: 200, name: 'b' });

BrowserWindow.getAllWindows('a'); // => [ windowA ]
BrowserWindow.getAllWindows({ width: 800 }); // => [ windowA, windowB ]
BrowserWindow.getAllWindows({ name: 'b', width: 200 }); // => [ windowC ]

BrowerWindow.getAllWIndows({
has: { name: 'b' },
exclude: { width: 200 }
}) // => [ windowB ]
```

Add an `only` property to the `option`. When the `name` property is set, if the value of `only` is `true`, a new window will not be created. Instead, an existing window with the same `name` value will be returned and shown.

### Alternatives Considered

Add a `createWindow` method to `BrowserWindow`:
```javascript
BrowserWindow.createWindow(option, callback)
```
- `option` is the same as the `option` used in `new BrowserWindow(option)`.
- `callback` receives the `window` object, which can be used to add initialization behaviors to the window.

This method is used to create window instances without immediately generating the window. The window needs to be opened by calling the `open` method on the instance. This allows for centralized management of all windows within a module.

Example:
```javascript
// windows.js
const LoginWindow = BrowserWindow.createWindow({ width: 300, height: 200, show: false }, window => {
    window.loadFile('index.html');
    window.once('ready-to-show', () => { window.show(); });
});
const MainWindow = BrowserWindow.createWindow(foo, bar);
const SettingsWindow = BrowserWindow.createWindow(foo, bar);

export { LoginWindow, MainWindow, SettingsWindow };

---

// main.js
import { LoginWindow } from './windows.js';

app.whenReady().then(() => {
    LoginWindow.open(); // Equivalent to the following code ↓
});

// Equivalent code
const loginWindow = new BrowserWindow({ width: 300, height: 200, show: false });
loginWindow.loadFile('index.html');
loginWindow.once('ready-to-show', () => { window.show(); });
```

If there is a `createWindow` method, a `setDefaultOption` method should also be added. The `option` parameter of `createWindow` would override the default options, resulting in the final options.

### Additional Information

This is a method I wrote to implement "Alternatives Considered," but through `CreateWindow.option`, not all properties can be obtained, only instance properties. It would be great if the `option` supported retrieving all window options.
```javascript
const { BrowserWindow } = require('electron')
const { join } = require('path');
const { format } = require('url')

class CreateWindow {
    #callback
    constructor(option, callback = new Function) {
        this.option = option
        this.window
        this.#callback = callback
    }
    open() {
        if (this.option?.title) {
            for (let window of BrowserWindow.getAllWindows()) {
                if (window.getTitle() === this.option.title) {
                    window.show()
                    return window
                }
            }
        }
        const optionDefault = {
            width: 800,
            height: 600,
            show: false,
            webPreferences: {
                preload: join(__dirname, 'preload.js'),
            },
            parent: this.option?.modal ? BrowserWindow.getAllWindows()[0] : null,
            autoHideMenuBar: MAIN_WINDOW_VITE_DEV_SERVER_URL ? !this.option?.menu : false,
        }
        // 创建窗体
        const window = new BrowserWindow({
            ...optionDefault,
            ...this.option,
        })
        if (this.option?.menu) window.setMenu(this.option.menu)

        window.once('ready-to-show', () => {
            if (this.option?.title) window.setTitle(this.option.title)
            this.show()
        })

        // and load the index.html of the app.
        if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
            const _url = new URL(MAIN_WINDOW_VITE_DEV_SERVER_URL)
            _url.hash = this.option?.path ? this.option.path : ''
            console.log(_url.toString())
            window.loadURL(_url.toString())
            // Open the DevTools.
            window.webContents.openDevTools();
        } else {
            window.loadFile(
                join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`),
                { hash: this.option?.path ? format(this.option.path) : '' }
            )
        }
        this.#callback(window)
        this.window = window
        return window
    }
    close() { this.window?.close() }
    destroy() { this.window?.destroy() }
    hide() { this.window?.hide() }
    show() { this.window?.show() }
}

export { CreateWindow }
```