Skip to content

Commit d64cd6c

Browse files
committed
Add CefLifeSpanHandler.onAfterParentChanged notification.
This supports asynchronous continuation of reparenting operations.
1 parent 924710e commit d64cd6c

13 files changed

Lines changed: 131 additions & 41 deletions

java/org/cef/CefClient.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,12 @@ public void onAfterCreated(CefBrowser browser) {
516516
if (lifeSpanHandler_ != null) lifeSpanHandler_.onAfterCreated(browser);
517517
}
518518

519+
@Override
520+
public void onAfterParentChanged(CefBrowser browser) {
521+
if (browser == null) return;
522+
if (lifeSpanHandler_ != null) lifeSpanHandler_.onAfterParentChanged(browser);
523+
}
524+
519525
@Override
520526
public boolean doClose(CefBrowser browser) {
521527
if (browser == null) return false;

java/org/cef/browser/CefBrowserWr.java

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ private CefBrowserWr(CefClient client, String url, CefRequestContext context,
178178
// We're using a JComponent instead of a Canvas now because the
179179
// JComponent has clipping informations, which aren't accessible for Canvas.
180180
component_ = new JPanel(new BorderLayout()) {
181+
private boolean removed_ = true;
182+
181183
@Override
182184
public void setBounds(int x, int y, int width, int height) {
183185
super.setBounds(x, y, width, height);
@@ -217,38 +219,29 @@ public void paint(Graphics g) {
217219
@Override
218220
public void addNotify() {
219221
super.addNotify();
220-
if (OS.isMacintosh()) {
221-
setParent(getWindowHandle(this), null);
222+
if (removed_) {
223+
setParent(getWindowHandle(this), canvas_);
224+
removed_ = false;
222225
}
223226
}
224227

225228
@Override
226229
public void removeNotify() {
227-
if (!isClosed() && OS.isMacintosh()) {
228-
setParent(0, null);
230+
if (!removed_) {
231+
if (!isClosed()) {
232+
setParent(0, null);
233+
}
234+
removed_ = true;
229235
}
230236
super.removeNotify();
231237
}
232238
};
239+
233240
// On windows we have to use a Canvas because its a heavyweight component
234241
// and we need its native HWND as parent for the browser UI. The same
235242
// technique is used on Linux as well.
236243
if (OS.isWindows() || OS.isLinux()) {
237-
canvas_ = new Canvas() {
238-
@Override
239-
public void addNotify() {
240-
super.addNotify();
241-
setParent(0, this);
242-
}
243-
244-
@Override
245-
public void removeNotify() {
246-
if (!isClosed()) {
247-
setParent(0, null);
248-
}
249-
super.removeNotify();
250-
}
251-
};
244+
canvas_ = new Canvas();
252245
((JPanel) component_).add(canvas_, BorderLayout.CENTER);
253246
}
254247

java/org/cef/handler/CefLifeSpanHandler.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ boolean onBeforePopup(
6060
*/
6161
public void onAfterCreated(CefBrowser browser);
6262

63+
/**
64+
* Called after a browser's native parent window has changed.
65+
*
66+
* @param browser The browser generating the event.
67+
*/
68+
public void onAfterParentChanged(CefBrowser browser);
69+
6370
/**
6471
* Called when a browser has received a request to close.
6572
*

java/org/cef/handler/CefLifeSpanHandlerAdapter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public boolean onBeforePopup(
2222
@Override
2323
public void onAfterCreated(CefBrowser browser) {}
2424

25+
@Override
26+
public void onAfterParentChanged(CefBrowser browser) {}
27+
2528
@Override
2629
public boolean doClose(CefBrowser browser) {
2730
return false;

java/tests/detailed/BrowserFrame.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.awt.event.WindowAdapter;
88
import java.awt.event.WindowEvent;
99
import javax.swing.JFrame;
10+
import javax.swing.SwingUtilities;
1011

1112
import org.cef.CefApp;
1213
import org.cef.browser.CefBrowser;
@@ -16,6 +17,7 @@ public class BrowserFrame extends JFrame {
1617
private boolean isClosed_ = false;
1718
private CefBrowser browser_ = null;
1819
private static int browserCount_ = 0;
20+
private Runnable afterParentChangedAction_ = null;
1921

2022
public BrowserFrame() {
2123
this(null);
@@ -90,6 +92,16 @@ public void onAfterCreated(CefBrowser browser) {
9092
browserCount_++;
9193
}
9294

95+
@Override
96+
public void onAfterParentChanged(CefBrowser browser) {
97+
System.out.println(
98+
"BrowserFrame.onAfterParentChanged id=" + browser.getIdentifier());
99+
if (afterParentChangedAction_ != null) {
100+
SwingUtilities.invokeLater(afterParentChangedAction_);
101+
afterParentChangedAction_ = null;
102+
}
103+
}
104+
93105
@Override
94106
public boolean doClose(CefBrowser browser) {
95107
boolean result = browser.doClose();
@@ -109,8 +121,13 @@ public void onBeforeClose(CefBrowser browser) {
109121
});
110122
}
111123

112-
public void removeBrowser() {
124+
public void removeBrowser(Runnable r) {
125+
System.out.println("BrowserFrame.removeBrowser");
126+
afterParentChangedAction_ = r;
113127
remove(browser_.getUIComponent());
128+
// The removeNotify() notification should be sent as a result of calling remove().
129+
// However, it isn't in all cases so we do it manually here.
130+
browser_.getUIComponent().removeNotify();
114131
browser_ = null;
115132
}
116133

java/tests/detailed/ui/MenuBar.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public void visit(String string) {
7777
private final ControlPanel control_pane_;
7878
private final DownloadDialog downloadDialog_;
7979
private final CefCookieManager cookieManager_;
80+
private boolean reparentPending_ = false;
8081

8182
public MenuBar(BrowserFrame owner, CefBrowser browser, ControlPanel control_pane,
8283
DownloadDialog downloadDialog, CefCookieManager cookieManager) {
@@ -405,20 +406,31 @@ public void actionPerformed(ActionEvent e) {
405406
reparentButton.addActionListener(new ActionListener() {
406407
@Override
407408
public void actionPerformed(ActionEvent e) {
409+
if (reparentPending_) return;
410+
reparentPending_ = true;
411+
408412
if (reparentButton.getText().equals("Reparent <")) {
409-
owner_.removeBrowser();
410-
newFrame.add(browser_.getUIComponent(), BorderLayout.CENTER);
411-
newFrame.setBrowser(browser_);
412-
reparentButton.setText("Reparent >");
413+
owner_.removeBrowser(new Runnable() {
414+
public void run() {
415+
newFrame.add(browser_.getUIComponent(), BorderLayout.CENTER);
416+
newFrame.setBrowser(browser_);
417+
reparentButton.setText("Reparent >");
418+
reparentPending_ = false;
419+
}
420+
});
413421
} else {
414-
newFrame.removeBrowser();
415-
JRootPane rootPane = (JRootPane) owner_.getComponent(0);
416-
Container container = rootPane.getContentPane();
417-
JPanel panel = (JPanel) container.getComponent(0);
418-
panel.add(browser_.getUIComponent());
419-
owner_.setBrowser(browser_);
420-
owner_.revalidate();
421-
reparentButton.setText("Reparent <");
422+
newFrame.removeBrowser(new Runnable() {
423+
public void run() {
424+
JRootPane rootPane = (JRootPane) owner_.getComponent(0);
425+
Container container = rootPane.getContentPane();
426+
JPanel panel = (JPanel) container.getComponent(0);
427+
panel.add(browser_.getUIComponent());
428+
owner_.setBrowser(browser_);
429+
owner_.revalidate();
430+
reparentButton.setText("Reparent <");
431+
reparentPending_ = false;
432+
}
433+
});
422434
}
423435
}
424436
});

native/CefBrowser_N.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,24 @@ void getZoomLevel(CefRefPtr<CefBrowserHost> host,
998998
}
999999
}
10001000

1001+
void OnAfterParentChanged(CefRefPtr<CefBrowser> browser) {
1002+
if (!CefCurrentlyOn(TID_UI)) {
1003+
CefPostTask(TID_UI, base::Bind(&OnAfterParentChanged, browser));
1004+
return;
1005+
}
1006+
1007+
if (browser->GetHost()->GetClient()) {
1008+
CefRefPtr<LifeSpanHandler> lifeSpanHandler =
1009+
(LifeSpanHandler*)browser->GetHost()
1010+
->GetClient()
1011+
->GetLifeSpanHandler()
1012+
.get();
1013+
if (lifeSpanHandler) {
1014+
lifeSpanHandler->OnAfterParentChanged(browser);
1015+
}
1016+
}
1017+
}
1018+
10011019
} // namespace
10021020

10031021
JNIEXPORT jboolean JNICALL
@@ -1880,18 +1898,20 @@ Java_org_cef_browser_CefBrowser_1N_N_1SetParent(JNIEnv* env,
18801898
jlong windowHandle,
18811899
jobject canvas) {
18821900
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
1901+
const base::Closure& callback = base::Bind(OnAfterParentChanged, browser);
18831902

18841903
#if defined(OS_MACOSX)
1885-
util::SetParent(browser->GetHost()->GetWindowHandle(), windowHandle);
1904+
util::SetParent(browser->GetHost()->GetWindowHandle(), windowHandle,
1905+
callback);
18861906
#else
18871907
CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle();
18881908
CefWindowHandle parentHandle =
18891909
canvas ? util::GetWindowHandle(env, canvas) : kNullWindowHandle;
18901910
if (CefCurrentlyOn(TID_UI)) {
1891-
util::SetParent(browserHandle, parentHandle);
1911+
util::SetParent(browserHandle, parentHandle, callback);
18921912
} else {
1893-
CefPostTask(TID_UI,
1894-
base::Bind(util::SetParent, browserHandle, parentHandle));
1913+
CefPostTask(TID_UI, base::Bind(util::SetParent, browserHandle, parentHandle,
1914+
callback));
18951915
}
18961916
#endif
18971917
}

native/life_span_handler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ void LifeSpanHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
102102
client->OnBeforeClose(browser);
103103
}
104104

105+
void LifeSpanHandler::OnAfterParentChanged(CefRefPtr<CefBrowser> browser) {
106+
REQUIRE_UI_THREAD();
107+
JNIEnv* env = GetJNIEnv();
108+
if (!env)
109+
return;
110+
jobject jbrowser = GetJNIBrowser(browser);
111+
JNI_CALL_VOID_METHOD(env, jhandler_, "onAfterParentChanged",
112+
"(Lorg/cef/browser/CefBrowser;)V", jbrowser);
113+
}
114+
105115
void LifeSpanHandler::registerJBrowser(jobject browser) {
106116
jbrowsers_.push_back(browser);
107117
}

native/life_span_handler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class LifeSpanHandler : public CefLifeSpanHandler {
3232
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
3333
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
3434

35+
void OnAfterParentChanged(CefRefPtr<CefBrowser> browser);
36+
3537
void registerJBrowser(jobject browser);
3638
void unregisterJBrowser(jobject browser);
3739

native/util.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <jni.h>
1414

15+
#include "include/base/cef_callback_forward.h"
1516
#include "include/cef_browser.h"
1617
#include "include/cef_task.h"
1718

@@ -92,7 +93,9 @@ void DestroyCefBrowser(CefRefPtr<CefBrowser> browser);
9293

9394
// Set the parent of |browserHandle|. If the parent is NULL the browser will be
9495
// parented to the TempWindow.
95-
void SetParent(CefWindowHandle browserHandle, jlong parentHandle);
96+
void SetParent(CefWindowHandle browserHandle,
97+
jlong parentHandle,
98+
const base::Closure& callback);
9699

97100
#else // !defined(OS_MACOSX)
98101

@@ -101,7 +104,9 @@ CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas);
101104

102105
// Set the parent of |browserHandle|. If the parent is NULL the browser will be
103106
// parented to the TempWindow.
104-
void SetParent(CefWindowHandle browserHandle, CefWindowHandle parentHandle);
107+
void SetParent(CefWindowHandle browserHandle,
108+
CefWindowHandle parentHandle,
109+
const base::Closure& callback);
105110

106111
// Set the window bounds for |browserHandle|.
107112
void SetWindowBounds(CefWindowHandle browserHandle, const CefRect& contentRect);

0 commit comments

Comments
 (0)