fix: correctly enable and disable windows on Windows and Linux (backport: 3-0-x) (#15255)

* fix: correctly enable and disable windows

* Move has_child_modal_ to NativeWindowViews

* Track modal children as an int instead of a bool

* Use correct types

* Move Increment/DecrementChildModals to NativeWindowViews

* Use parent() in NativeWindowViews

* Add test for not enabling disabled parent when modal child closes
This commit is contained in:
trop[bot] 2018-10-19 17:30:55 -07:00 committed by Shelley Vohr
parent 1c42715e1d
commit 9349b0a273
3 changed files with 54 additions and 17 deletions

View file

@ -342,7 +342,7 @@ bool NativeWindowViews::IsFocused() {
void NativeWindowViews::Show() { void NativeWindowViews::Show() {
if (is_modal() && NativeWindow::parent() && if (is_modal() && NativeWindow::parent() &&
!widget()->native_widget_private()->IsVisible()) !widget()->native_widget_private()->IsVisible())
NativeWindow::parent()->SetEnabled(false); static_cast<NativeWindowViews*>(parent())->IncrementChildModals();
widget()->native_widget_private()->ShowWithWindowState(GetRestoredState()); widget()->native_widget_private()->ShowWithWindowState(GetRestoredState());
@ -367,7 +367,7 @@ void NativeWindowViews::ShowInactive() {
void NativeWindowViews::Hide() { void NativeWindowViews::Hide() {
if (is_modal() && NativeWindow::parent()) if (is_modal() && NativeWindow::parent())
NativeWindow::parent()->SetEnabled(true); static_cast<NativeWindowViews*>(parent())->DecrementChildModals();
widget()->Hide(); widget()->Hide();
@ -391,16 +391,34 @@ bool NativeWindowViews::IsEnabled() {
#endif #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) { void NativeWindowViews::SetEnabled(bool enable) {
// Handle multiple calls of SetEnabled correctly. if (enable != is_enabled_) {
if (enable) { is_enabled_ = enable;
--disable_count_; SetEnabledInternal(ShouldBeEnabled());
if (disable_count_ != 0) }
return; }
} else {
++disable_count_; bool NativeWindowViews::ShouldBeEnabled() {
if (disable_count_ != 1) return is_enabled_ && (num_modal_children_ == 0);
return; }
void NativeWindowViews::SetEnabledInternal(bool enable) {
if (enable && IsEnabled()) {
return;
} else if (!enable && !IsEnabled()) {
return;
} }
#if defined(OS_WIN) #if defined(OS_WIN)
@ -1155,10 +1173,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
} }
void NativeWindowViews::DeleteDelegate() { void NativeWindowViews::DeleteDelegate() {
if (is_modal() && NativeWindow::parent()) { if (is_modal() && this->parent()) {
auto* parent = NativeWindow::parent(); auto* parent = this->parent();
// Enable parent window after current window gets closed. // Enable parent window after current window gets closed.
parent->SetEnabled(true); static_cast<NativeWindowViews*>(parent)->DecrementChildModals();
// Focus on parent window. // Focus on parent window.
parent->Focus(true); parent->Focus(true);
} }

View file

@ -129,6 +129,9 @@ class NativeWindowViews : public NativeWindow,
void UpdateDraggableRegions(std::unique_ptr<SkRegion> region); void UpdateDraggableRegions(std::unique_ptr<SkRegion> region);
void IncrementChildModals();
void DecrementChildModals();
#if defined(OS_WIN) #if defined(OS_WIN)
void SetIcon(HICON small_icon, HICON app_icon); void SetIcon(HICON small_icon, HICON app_icon);
#elif defined(USE_X11) #elif defined(USE_X11)
@ -185,6 +188,10 @@ class NativeWindowViews : public NativeWindow,
LPARAM l_param); LPARAM l_param);
#endif #endif
// Enable/disable:
bool ShouldBeEnabled();
void SetEnabledInternal(bool enabled);
// NativeWindow: // NativeWindow:
void HandleKeyboardEvent( void HandleKeyboardEvent(
content::WebContents*, content::WebContents*,
@ -268,8 +275,11 @@ class NativeWindowViews : public NativeWindow,
// has to been explicitly provided. // has to been explicitly provided.
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag. std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
// How many times the Disable has been called. // Whether the window should be enabled based on user calls to SetEnabled()
int disable_count_ = 0; 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 use_content_size_ = false;
bool movable_ = true; bool movable_ = true;

View file

@ -2747,7 +2747,7 @@ describe('BrowserWindow module', () => {
c.show() c.show()
assert.equal(w.isEnabled(), false) assert.equal(w.isEnabled(), false)
}) })
it('enables parent window when closed', (done) => { it('re-enables an enabled parent window when closed', (done) => {
c.once('closed', () => { c.once('closed', () => {
assert.equal(w.isEnabled(), true) assert.equal(w.isEnabled(), true)
done() done()
@ -2755,6 +2755,15 @@ describe('BrowserWindow module', () => {
c.show() c.show()
c.close() 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', () => { it('disables parent window recursively', () => {
let c2 = new BrowserWindow({show: false, parent: w, modal: true}) let c2 = new BrowserWindow({show: false, parent: w, modal: true})
c.show() c.show()