Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(543)

Side by Side Diff: ui/views/window/dialog_client_view.cc

Issue 2825243002: DialogClientView: Handle nested close requests gracefully.
Patch Set: Self review Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/window/dialog_client_view.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/window/dialog_client_view.h" 5 #include "ui/views/window/dialog_client_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "build/build_config.h" 9 #include "build/build_config.h"
10 #include "ui/base/material_design/material_design_controller.h" 10 #include "ui/base/material_design/material_design_controller.h"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 // Doing this now ensures this accelerator will have lower priority than 80 // Doing this now ensures this accelerator will have lower priority than
81 // one set by the contents view. 81 // one set by the contents view.
82 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); 82 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
83 button_row_container_ = new ButtonRowContainer(this); 83 button_row_container_ = new ButtonRowContainer(this);
84 AddChildView(button_row_container_); 84 AddChildView(button_row_container_);
85 } 85 }
86 86
87 DialogClientView::~DialogClientView() {} 87 DialogClientView::~DialogClientView() {}
88 88
89 void DialogClientView::AcceptWindow() { 89 void DialogClientView::AcceptWindow() {
90 // Only notify the delegate once. See |delegate_allowed_close_|'s comment. 90 CloseWithDelegateMethod(&DialogDelegate::Accept, true);
91 if (!delegate_allowed_close_ && GetDialogDelegate()->Accept()) {
92 delegate_allowed_close_ = true;
93 GetWidget()->Close();
94 }
95 } 91 }
96 92
97 void DialogClientView::CancelWindow() { 93 void DialogClientView::CancelWindow() {
98 // Only notify the delegate once. See |delegate_allowed_close_|'s comment. 94 CloseWithDelegateMethod(&DialogDelegate::Cancel, true);
99 if (!delegate_allowed_close_ && GetDialogDelegate()->Cancel()) {
100 delegate_allowed_close_ = true;
101 GetWidget()->Close();
102 }
103 } 95 }
104 96
105 void DialogClientView::UpdateDialogButtons() { 97 void DialogClientView::UpdateDialogButtons() {
106 SetupLayout(); 98 SetupLayout();
107 InvalidateLayout(); 99 InvalidateLayout();
108 } 100 }
109 101
110 /////////////////////////////////////////////////////////////////////////////// 102 ///////////////////////////////////////////////////////////////////////////////
111 // DialogClientView, ClientView overrides: 103 // DialogClientView, ClientView overrides:
112 104
113 bool DialogClientView::CanClose() { 105 bool DialogClientView::CanClose() {
106 if (delegate_allowed_close_) {
107 DCHECK(!asking_delegate_whether_to_close_);
108 return true;
109 }
110
111 // The delegate may perform an action that causes the Widget to lose focus and
112 // (for some bubbles) attempt to close again. Widget::Close() has protection
113 // against multiple calls to Widget::Close(), but that method is above
114 // CanClose() in the stack: CanClose() has not yet told the first
115 // Widget::Close() whether it may proceed, so that protection can't be used.
116 // Detect this situation and always return false from the nested call to
117 // CanClose() so that Widget::Close() bails out early.
118 if (asking_delegate_whether_to_close_)
119 return false;
120
114 // If the dialog is closing but no Accept or Cancel action has been performed 121 // If the dialog is closing but no Accept or Cancel action has been performed
115 // before, it's a Close action. 122 // before, it's a Close action.
116 if (!delegate_allowed_close_) 123 CloseWithDelegateMethod(&DialogDelegate::Close, false);
117 delegate_allowed_close_ = GetDialogDelegate()->Close();
118 return delegate_allowed_close_; 124 return delegate_allowed_close_;
119 } 125 }
120 126
121 DialogClientView* DialogClientView::AsDialogClientView() { 127 DialogClientView* DialogClientView::AsDialogClientView() {
122 return this; 128 return this;
123 } 129 }
124 130
125 const DialogClientView* DialogClientView::AsDialogClientView() const { 131 const DialogClientView* DialogClientView::AsDialogClientView() const {
126 return this; 132 return this;
127 } 133 }
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL); 418 UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL);
413 419
414 if (extra_view_) 420 if (extra_view_)
415 return; 421 return;
416 422
417 extra_view_ = GetDialogDelegate()->CreateExtraView(); 423 extra_view_ = GetDialogDelegate()->CreateExtraView();
418 if (extra_view_) 424 if (extra_view_)
419 extra_view_->SetGroup(kButtonGroup); 425 extra_view_->SetGroup(kButtonGroup);
420 } 426 }
421 427
428 void DialogClientView::CloseWithDelegateMethod(bool (DialogDelegate::*method)(),
429 bool close) {
430 DCHECK(!asking_delegate_whether_to_close_);
431
432 // Only notify the delegate once. See |delegate_allowed_close_|'s comment.
433 if (delegate_allowed_close_)
434 return;
435
436 {
437 base::AutoReset<bool> auto_reset(&asking_delegate_whether_to_close_, true);
438 delegate_allowed_close_ = (GetDialogDelegate()->*method)();
439 }
440 if (close && delegate_allowed_close_)
441 GetWidget()->Close();
442 }
443
422 } // namespace views 444 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/window/dialog_client_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698