From 51f3fb9bdeee8de9b09aa4ba95ce20713d8bab9b Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 18 Oct 2018 14:23:40 -0700 Subject: [PATCH] fix: correctly enable and disable windows on Windows and Linux (#15184) --- atom/browser/native_window_views.cc | 46 ++++++++++++++++++++--------- atom/browser/native_window_views.h | 14 +++++++-- spec/api-browser-window-spec.js | 11 ++++++- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 8f3d9a2dc70d..08edb6e91ee0 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -344,7 +344,7 @@ bool NativeWindowViews::IsFocused() { void NativeWindowViews::Show() { if (is_modal() && NativeWindow::parent() && !widget()->native_widget_private()->IsVisible()) - NativeWindow::parent()->SetEnabled(false); + static_cast(parent())->IncrementChildModals(); widget()->native_widget_private()->ShowWithWindowState(GetRestoredState()); @@ -369,7 +369,7 @@ void NativeWindowViews::ShowInactive() { void NativeWindowViews::Hide() { if (is_modal() && NativeWindow::parent()) - NativeWindow::parent()->SetEnabled(true); + static_cast(parent())->DecrementChildModals(); widget()->Hide(); @@ -393,16 +393,34 @@ bool NativeWindowViews::IsEnabled() { #endif } +void NativeWindowViews::IncrementChildModals() { + num_modal_children_++; + SetEnabledInternal(ShouldBeEnabled()); +} + +void NativeWindowViews::DecrementChildModals() { + if (num_modal_children_ > 0) { + num_modal_children_--; + } + SetEnabledInternal(ShouldBeEnabled()); +} + void NativeWindowViews::SetEnabled(bool enable) { - // Handle multiple calls of SetEnabled correctly. - if (enable) { - --disable_count_; - if (disable_count_ != 0) - return; - } else { - ++disable_count_; - if (disable_count_ != 1) - return; + if (enable != is_enabled_) { + is_enabled_ = enable; + SetEnabledInternal(ShouldBeEnabled()); + } +} + +bool NativeWindowViews::ShouldBeEnabled() { + return is_enabled_ && (num_modal_children_ == 0); +} + +void NativeWindowViews::SetEnabledInternal(bool enable) { + if (enable && IsEnabled()) { + return; + } else if (!enable && !IsEnabled()) { + return; } #if defined(OS_WIN) @@ -1161,10 +1179,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget, } void NativeWindowViews::DeleteDelegate() { - if (is_modal() && NativeWindow::parent()) { - auto* parent = NativeWindow::parent(); + if (is_modal() && this->parent()) { + auto* parent = this->parent(); // Enable parent window after current window gets closed. - parent->SetEnabled(true); + static_cast(parent)->DecrementChildModals(); // Focus on parent window. parent->Focus(true); } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 829982a70b05..e4cbb02d1eaa 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -134,6 +134,9 @@ class NativeWindowViews : public NativeWindow, void UpdateDraggableRegions(std::unique_ptr region); + void IncrementChildModals(); + void DecrementChildModals(); + #if defined(OS_WIN) void SetIcon(HICON small_icon, HICON app_icon); #elif defined(USE_X11) @@ -190,6 +193,10 @@ class NativeWindowViews : public NativeWindow, LPARAM l_param); #endif + // Enable/disable: + bool ShouldBeEnabled(); + void SetEnabledInternal(bool enabled); + // NativeWindow: void HandleKeyboardEvent( content::WebContents*, @@ -273,8 +280,11 @@ class NativeWindowViews : public NativeWindow, // has to been explicitly provided. std::unique_ptr draggable_region_; // used in custom drag. - // How many times the Disable has been called. - int disable_count_ = 0; + // Whether the window should be enabled based on user calls to SetEnabled() + bool is_enabled_ = true; + // How many modal children this window has; + // used to determine enabled state + unsigned int num_modal_children_ = 0; bool use_content_size_ = false; bool movable_ = true; diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 96f0b1b3c05f..58c8cecc1165 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -3014,7 +3014,7 @@ describe('BrowserWindow module', () => { c.show() assert.strictEqual(w.isEnabled(), false) }) - it('enables parent window when closed', (done) => { + it('re-enables an enabled parent window when closed', (done) => { c.once('closed', () => { assert.strictEqual(w.isEnabled(), true) done() @@ -3022,6 +3022,15 @@ describe('BrowserWindow module', () => { c.show() c.close() }) + it('does not re-enable a disabled parent window when closed', (done) => { + c.once('closed', () => { + assert.strictEqual(w.isEnabled(), false) + done() + }) + w.setEnabled(false) + c.show() + c.close() + }) it('disables parent window recursively', () => { const c2 = new BrowserWindow({ show: false, parent: w, modal: true }) c.show()