Skip to content

Commit

Permalink
Merge pull request #6026 from electron/ready-to-show
Browse files Browse the repository at this point in the history
Add "ready-to-show" event and docs on showing window gracefully
  • Loading branch information
zcbenz committed Jun 13, 2016
2 parents c422613 + fc09c98 commit fcc7dc7
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 9 deletions.
4 changes: 4 additions & 0 deletions atom/browser/api/atom_api_window.cc
Expand Up @@ -156,6 +156,10 @@ void Window::OnWindowHide() {
Emit("hide");
}

void Window::OnReadyToShow() {
Emit("ready-to-show");
}

void Window::OnWindowMaximize() {
Emit("maximize");
}
Expand Down
1 change: 1 addition & 0 deletions atom/browser/api/atom_api_window.h
Expand Up @@ -61,6 +61,7 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowFocus() override;
void OnWindowShow() override;
void OnWindowHide() override;
void OnReadyToShow() override;
void OnWindowMaximize() override;
void OnWindowUnmaximize() override;
void OnWindowMinimize() override;
Expand Down
20 changes: 20 additions & 0 deletions atom/browser/native_window.cc
Expand Up @@ -560,6 +560,22 @@ void NativeWindow::BeforeUnloadDialogCancelled() {
window_unresposive_closure_.Cancel();
}

void NativeWindow::DidFirstVisuallyNonEmptyPaint() {
if (IsVisible())
return;

// When there is a non-empty first paint, resize the RenderWidget to force
// Chromium to draw.
const auto view = web_contents()->GetRenderWidgetHostView();
view->Show();
view->SetSize(GetContentSize());

// Emit the ReadyToShow event in next tick in case of pending drawing work.
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&NativeWindow::NotifyReadyToShow, GetWeakPtr()));
}

bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
Expand Down Expand Up @@ -601,6 +617,10 @@ void NativeWindow::NotifyWindowUnresponsive() {
OnRendererUnresponsive());
}

void NativeWindow::NotifyReadyToShow() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnReadyToShow());
}

void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
const SkBitmap& bitmap,
content::ReadbackResponse response) {
Expand Down
4 changes: 4 additions & 0 deletions atom/browser/native_window.h
Expand Up @@ -275,6 +275,7 @@ class NativeWindow : public base::SupportsUserData,
// content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadDialogCancelled() override;
void DidFirstVisuallyNonEmptyPaint() override;
bool OnMessageReceived(const IPC::Message& message) override;

private:
Expand All @@ -284,6 +285,9 @@ class NativeWindow : public base::SupportsUserData,
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();

// Dispatch ReadyToShow event to observers.
void NotifyReadyToShow();

// Called when CapturePage has done.
void OnCapturePageDone(const CapturePageCallback& callback,
const SkBitmap& bitmap,
Expand Down
3 changes: 3 additions & 0 deletions atom/browser/native_window_observer.h
Expand Up @@ -48,6 +48,9 @@ class NativeWindowObserver {
// Called when window is hidden.
virtual void OnWindowHide() {}

// Called when window is ready to show.
virtual void OnReadyToShow() {}

// Called when window state changed.
virtual void OnWindowMaximize() {}
virtual void OnWindowUnmaximize() {}
Expand Down
61 changes: 52 additions & 9 deletions docs/api/browser-window.md
Expand Up @@ -4,22 +4,60 @@
```javascript
// In the main process.
const {BrowserWindow} = require('electron');
const {BrowserWindow} = require('electron')

// Or in the renderer process.
const {BrowserWindow} = require('electron').remote;
const {BrowserWindow} = require('electron').remote

let win = new BrowserWindow({width: 800, height: 600, show: false});
let win = new BrowserWindow({width: 800, height: 600})
win.on('closed', () => {
win = null;
});
win = null
})

win.loadURL('https://github.com')
```

## Frameless window

To create a window without chrome, or a transparent window in arbitrary shape,
you can use the [Frameless Window](frameless-window.md) API.

## Showing window gracefully

When loading a page in window directly, users will see the progress of loading
page, which is not good experience for native app. To make the window display
without visual flash, there are two solutions for different situations.

### Using `ready-to-show` event

While loading the page, the `ready-to-show` event will be emitted when renderer
process has done drawing for the first time, showing window after this event
will have no visual flash:

win.loadURL('https://github.com');
win.show();
```javascript
let win = new BrowserWindow({show: false})
win.once('ready-to-show', () => {
win.show()
})
```

You can also create a window without chrome by using
[Frameless Window](frameless-window.md) API.
This is event is usually emitted after the `did-finish-load` event, but for
pages with many remote resources, it may be emitted before the `did-finish-load`
event.

### Setting `backgroundColor`

For a complex app, the `ready-to-show` event could be emitted too late, making
the app feel slow. In this case, it is recommended to show the window
immediately, and use a `backgroundColor` close to your app's background:

```javascript
let win = new BrowserWindow({backgroundColor: '#2e2c29'})
win.loadURL('https://github.com')
```

Note that even for apps that use `ready-to-show` event, it is still recommended
to set `backgroundColor` to make app feel more native.

## Class: BrowserWindow

Expand Down Expand Up @@ -271,6 +309,11 @@ Emitted when the window is shown.

Emitted when the window is hidden.

### Event: 'ready-to-show'

Emitted when the web page has been rendered and window can be displayed without
visual flash.

### Event: 'maximize'

Emitted when window is maximized.
Expand Down

0 comments on commit fcc7dc7

Please sign in to comment.