diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index b72c62704ed2..a3df8f9c08d8 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -144,6 +144,17 @@ void Window::WillCloseWindow(bool* prevent_default) { *prevent_default = Emit("close"); } +void Window::WillDestoryNativeObject() { + // Close all child windows before closing current window. + v8::Locker locker(isolate()); + v8::HandleScope handle_scope(isolate()); + for (v8::Local value : child_windows_.Values(isolate())) { + mate::Handle child; + if (mate::ConvertFromV8(isolate(), value, &child)) + child->window_->CloseImmediately(); + } +} + void Window::OnWindowClosed() { api_web_contents_->DestroyWebContents(); @@ -734,6 +745,7 @@ void Window::SetModal(bool modal, mate::Arguments* args) { parent->Disable(); else parent->Enable(); + window_->SetModal(modal); is_modal_ = modal; } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index e5522f958e07..238e3ad7e1f0 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -60,6 +60,7 @@ class Window : public mate::TrackableObject, // NativeWindowObserver: void WillCloseWindow(bool* prevent_default) override; + void WillDestoryNativeObject() override; void OnWindowClosed() override; void OnWindowBlur() override; void OnWindowFocus() override; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 73698b7f4127..2ce6779d6205 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -403,6 +403,9 @@ void NativeWindow::CloseContents(content::WebContents* source) { inspectable_web_contents_ = nullptr; Observe(nullptr); + FOR_EACH_OBSERVER(NativeWindowObserver, observers_, + WillDestoryNativeObject()); + // When the web contents is gone, close the window immediately, but the // memory will not be freed until you call delete. // In this way, it would be safe to manage windows via smart pointers. If you diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index bcfa487b9750..d20146819d48 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -165,6 +165,7 @@ class NativeWindow : public base::SupportsUserData, virtual void SetParentWindow(NativeWindow* parent) = 0; virtual void BeginSheet(NativeWindow* sheet); virtual void EndSheet(NativeWindow* sheet); + virtual void SetModal(bool modal) = 0; virtual gfx::NativeWindow GetNativeWindow() = 0; virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0; diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 0806cfa28c3d..3061663520ad 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -85,6 +85,7 @@ class NativeWindowMac : public NativeWindow { void SetParentWindow(NativeWindow* parent) override; void BeginSheet(NativeWindow* sheet) override; void EndSheet(NativeWindow* sheet) override; + void SetModal(bool modal) override; gfx::NativeWindow GetNativeWindow() override; gfx::AcceleratedWidget GetAcceleratedWidget() override; void SetProgressBar(double progress) override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 90b62cf7d2d1..f68d49929ab9 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -634,10 +634,6 @@ void NativeWindowMac::Close() { } void NativeWindowMac::CloseImmediately() { - // Close all child windows before closing this window. - for (NSWindow* child in [window_ childWindows]) - [child close]; - [window_ close]; } @@ -981,6 +977,9 @@ void NativeWindowMac::EndSheet(NativeWindow* sheet) { sheet->CloseImmediately(); } +void NativeWindowMac::SetModal(bool modal) { +} + gfx::NativeWindow NativeWindowMac::GetNativeWindow() { return window_; } diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h index 73bf4362f57f..16541d090900 100644 --- a/atom/browser/native_window_observer.h +++ b/atom/browser/native_window_observer.h @@ -33,6 +33,9 @@ class NativeWindowObserver { // Called when the window is gonna closed. virtual void WillCloseWindow(bool* prevent_default) {} + // Called before the native window object is going to be destroyed. + virtual void WillDestoryNativeObject() {} + // Called when the window is closed. virtual void OnWindowClosed() {} diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 803a3e215376..f5c21bed74ee 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -187,10 +187,10 @@ NativeWindowViews::NativeWindowViews( if (options.Get(options::kFocusable, &focusable) && !focusable) params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; +#if defined(OS_WIN) if (parent) params.parent = parent->GetNativeWindow(); -#if defined(OS_WIN) params.native_widget = new views::DesktopNativeWidgetAura(window_.get()); atom_desktop_window_tree_host_win_ = new AtomDesktopWindowTreeHostWin( @@ -248,6 +248,9 @@ NativeWindowViews::NativeWindowViews( std::string window_type; if (options.Get(options::kType, &window_type)) SetWindowType(GetAcceleratedWidget(), window_type); + + if (parent) + SetParentWindow(parent); #endif // Add web view. @@ -379,15 +382,25 @@ bool NativeWindowViews::IsVisible() { } void NativeWindowViews::Disable() { +#if defined(OS_WIN) ::EnableWindow(GetAcceleratedWidget(), FALSE); +#elif defined(USE_X11) +#endif } void NativeWindowViews::Enable() { +#if defined(OS_WIN) ::EnableWindow(GetAcceleratedWidget(), TRUE); +#elif defined(USE_X11) +#endif } bool NativeWindowViews::IsEnabled() { +#if defined(OS_WIN) return ::IsWindowEnabled(GetAcceleratedWidget()); +#else + return false; +#endif } void NativeWindowViews::Maximize() { @@ -790,9 +803,14 @@ void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) { } void NativeWindowViews::SetParentWindow(NativeWindow* parent) { +#if defined(USE_X11) + XDisplay* xdisplay = gfx::GetXDisplay(); + XSetTransientForHint( + xdisplay, GetAcceleratedWidget(), + parent? parent->GetAcceleratedWidget() : DefaultRootWindow(xdisplay)); +#elif defined(OS_WIN) && defined(DEBUG) // Should work, but does not, it seems that the views toolkit doesn't support // reparenting on desktop. -#if defined(DEBUG) if (parent) { ::SetParent(GetAcceleratedWidget(), parent->GetAcceleratedWidget()); views::Widget::ReparentNativeView(GetNativeWindow(), @@ -801,12 +819,21 @@ void NativeWindowViews::SetParentWindow(NativeWindow* parent) { } else { if (!GetNativeWindow()->parent()) return; + ::SetParent(GetAcceleratedWidget(), NULL); views::Widget::ReparentNativeView(GetNativeWindow(), nullptr); wm::RemoveTransientChild(GetNativeWindow()->parent(), GetNativeWindow()); } #endif } +void NativeWindowViews::SetModal(bool modal) { +#if defined(USE_X11) + SetWMSpecState(GetAcceleratedWidget(), modal, + GetAtom("_NET_WM_STATE_MODAL")); + SetWindowType(GetAcceleratedWidget(), modal ? "dialog" : "normal"); +#endif +} + gfx::NativeWindow NativeWindowViews::GetNativeWindow() { return window_->GetNativeWindow(); } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 95a95120f46d..b38572d9d2ad 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -99,6 +99,7 @@ class NativeWindowViews : public NativeWindow, void SetFocusable(bool focusable) override; void SetMenu(ui::MenuModel* menu_model) override; void SetParentWindow(NativeWindow* parent) override; + void SetModal(bool modal) override; gfx::NativeWindow GetNativeWindow() override; void SetOverlayIcon(const gfx::Image& overlay, const std::string& description) override; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 51f7d2514859..e9813af5b759 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -868,7 +868,7 @@ describe('browser-window module', function () { }) describe('win.setParentWindow(parent)', function () { - if (process.platform !== 'darwin') return + if (process.platform === 'win32') return beforeEach(function () { if (c != null) c.destroy()