Created
December 11, 2024 20:57
-
-
Save johnlindquist/892635da6969d48777edd7caac05a21b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Let me break down how `showInactive()` works on Windows and explain the rendering behavior: | |
1. For Windows, `showInactive()` is implemented in `native_window_views.cc`: | |
```478:487:shell/browser/native_window_views.cc | |
void NativeWindowViews::ShowInactive() { | |
widget()->ShowInactive(); | |
NotifyWindowShow(); | |
#if defined(USE_X11) | |
if (global_menu_bar_) | |
global_menu_bar_->OnWindowMapped(); | |
#endif | |
} | |
``` | |
The key is that it calls `widget()->ShowInactive()` which maps to the Win32 API call `ShowWindow(hwnd, SW_SHOWNOACTIVATE)`. This shows the window without giving it focus or bringing it to the foreground. | |
2. As for why rendering happens after calling `show()`, this is due to a chain of events: | |
When `show()` is called: | |
```460:476:shell/browser/native_window_views.cc | |
void NativeWindowViews::Show() { | |
if (is_modal() && NativeWindow::parent() && | |
!widget()->native_widget_private()->IsVisible()) | |
static_cast<NativeWindowViews*>(parent())->IncrementChildModals(); | |
widget()->native_widget_private()->Show(GetRestoredState(), gfx::Rect()); | |
// explicitly focus the window | |
widget()->Activate(); | |
NotifyWindowShow(); | |
#if defined(USE_X11) | |
if (global_menu_bar_) | |
global_menu_bar_->OnWindowMapped(); | |
#endif | |
} | |
``` | |
This triggers three important things: | |
1. `widget()->native_widget_private()->Show()` - Makes the window visible | |
2. `widget()->Activate()` - Gives the window focus | |
3. `NotifyWindowShow()` - Sends notifications about visibility change | |
The key to rendering is in `BrowserWindow::OnWindowShow()`: | |
```485:488:shell/browser/api/electron_api_browser_window.cc | |
void BrowserWindow::OnWindowShow() { | |
web_contents()->WasShown(); | |
BaseWindow::OnWindowShow(); | |
} | |
``` | |
The critical line is `web_contents()->WasShown()` which tells Chromium's content layer that the window is now visible. This triggers Chromium to: | |
1. Start the compositor | |
2. Allocate GPU resources | |
3. Begin actual rendering of web content | |
Before `show()` is called, Chromium keeps the renderer in a suspended state to conserve resources. This is why you don't see any rendering until after `show()`. | |
To implement similar behavior in another library, you would need to: | |
```cpp | |
// For showing without activation | |
void ShowWindowInactive(HWND hwnd) { | |
ShowWindow(hwnd, SW_SHOWNOACTIVATE); | |
} | |
// For normal show with rendering | |
void ShowWindow(HWND hwnd) { | |
ShowWindow(hwnd, SW_SHOW); | |
SetForegroundWindow(hwnd); | |
// Signal your rendering system to start | |
StartRendering(); | |
} | |
``` | |
The key difference between `show()` and `showInactive()` on Windows is: | |
- `show()`: Uses `SW_SHOW` + `SetForegroundWindow()` | |
- `showInactive()`: Uses `SW_SHOWNOACTIVATE` only | |
This is why `showInactive()` makes the window visible but doesn't steal focus or trigger the taskbar to flash. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment