linux: Implement win.setParentWindow(parent)
authorCheng Zhao <zcbenz@gmail.com>
Sun, 19 Jun 2016 06:47:27 +0000 (15:47 +0900)
committerCheng Zhao <zcbenz@gmail.com>
Mon, 20 Jun 2016 02:16:41 +0000 (11:16 +0900)
atom/browser/api/atom_api_window.cc
atom/browser/api/atom_api_window.h
atom/browser/native_window.cc
atom/browser/native_window.h
atom/browser/native_window_mac.h
atom/browser/native_window_mac.mm
atom/browser/native_window_observer.h
atom/browser/native_window_views.cc
atom/browser/native_window_views.h
spec/api-browser-window-spec.js

index b72c627..a3df8f9 100644 (file)
@@ -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<v8::Value> value : child_windows_.Values(isolate())) {
+    mate::Handle<Window> 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;
 }
 
index e5522f9..238e3ad 100644 (file)
@@ -60,6 +60,7 @@ class Window : public mate::TrackableObject<Window>,
 
   // NativeWindowObserver:
   void WillCloseWindow(bool* prevent_default) override;
+  void WillDestoryNativeObject() override;
   void OnWindowClosed() override;
   void OnWindowBlur() override;
   void OnWindowFocus() override;
index 73698b7..2ce6779 100644 (file)
@@ -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
index bcfa487..d201468 100644 (file)
@@ -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;
 
index 0806cfa..3061663 100644 (file)
@@ -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;
index 90b62cf..f68d499 100644 (file)
@@ -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_;
 }
index 73bf436..16541d0 100644 (file)
@@ -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() {}
 
index 803a3e2..f5c21be 100644 (file)
@@ -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();
 }
index 95a9512..b38572d 100644 (file)
@@ -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;
index 51f7d25..e9813af 100644 (file)
@@ -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()