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

Side by Side Diff: chrome/browser/ui/views/simple_message_box_views.cc

Issue 182143002: Use the default dispatcher where possible for nested message loops. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moar-fix Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/views/first_run_dialog.cc ('k') | ui/aura/client/dispatcher_client.h » ('j') | 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 "chrome/browser/ui/simple_message_box.h" 5 #include "chrome/browser/ui/simple_message_box.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_pump_dispatcher.h" 11 #include "base/message_loop/message_pump_dispatcher.h"
12 #include "base/run_loop.h" 12 #include "base/run_loop.h"
13 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/ui/views/constrained_window_views.h" 14 #include "chrome/browser/ui/views/constrained_window_views.h"
15 #include "grit/generated_resources.h" 15 #include "grit/generated_resources.h"
16 #include "ui/aura/client/dispatcher_client.h" 16 #include "ui/aura/client/dispatcher_client.h"
17 #include "ui/aura/env.h" 17 #include "ui/aura/env.h"
18 #include "ui/aura/window_event_dispatcher.h" 18 #include "ui/aura/window_event_dispatcher.h"
19 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/gfx/native_widget_types.h" 20 #include "ui/gfx/native_widget_types.h"
21 #include "ui/views/controls/message_box_view.h" 21 #include "ui/views/controls/message_box_view.h"
22 #include "ui/views/corewm/window_util.h"
22 #include "ui/views/widget/widget.h" 23 #include "ui/views/widget/widget.h"
23 #include "ui/views/window/dialog_delegate.h" 24 #include "ui/views/window/dialog_delegate.h"
24 25
25 #if defined(OS_WIN) 26 #if defined(OS_WIN)
26 #include "ui/base/win/message_box_win.h" 27 #include "ui/base/win/message_box_win.h"
27 #include "ui/views/win/hwnd_util.h" 28 #include "ui/views/win/hwnd_util.h"
28 #endif 29 #endif
29 30
30 namespace chrome { 31 namespace chrome {
31 32
32 namespace { 33 namespace {
33 34
34 // Multiple SimpleMessageBoxViews can show up at the same time. Each of these 35 // Multiple SimpleMessageBoxViews can show up at the same time. Each of these
35 // start a nested message-loop. However, these SimpleMessageBoxViews can be 36 // start a nested message-loop. However, these SimpleMessageBoxViews can be
36 // deleted in any order. This creates problems if a box in an inner-loop gets 37 // deleted in any order. This creates problems if a box in an inner-loop gets
37 // destroyed before a box in an outer-loop. So to avoid this, ref-counting is 38 // destroyed before a box in an outer-loop. So to avoid this, ref-counting is
38 // used so that the SimpleMessageBoxViews gets deleted at the right time. 39 // used so that the SimpleMessageBoxViews gets deleted at the right time.
39 class SimpleMessageBoxViews : public views::DialogDelegate, 40 class SimpleMessageBoxViews : public views::DialogDelegate,
40 public base::MessagePumpDispatcher,
41 public base::RefCounted<SimpleMessageBoxViews> { 41 public base::RefCounted<SimpleMessageBoxViews> {
42 public: 42 public:
43 SimpleMessageBoxViews(const base::string16& title, 43 SimpleMessageBoxViews(const base::string16& title,
44 const base::string16& message, 44 const base::string16& message,
45 MessageBoxType type, 45 MessageBoxType type,
46 const base::string16& yes_text, 46 const base::string16& yes_text,
47 const base::string16& no_text); 47 const base::string16& no_text);
48 48
49 MessageBoxResult result() const { return result_; } 49 MessageBoxResult result() const { return result_; }
50 50
51 // Overridden from views::DialogDelegate: 51 // Overridden from views::DialogDelegate:
52 virtual int GetDialogButtons() const OVERRIDE; 52 virtual int GetDialogButtons() const OVERRIDE;
53 virtual base::string16 GetDialogButtonLabel( 53 virtual base::string16 GetDialogButtonLabel(
54 ui::DialogButton button) const OVERRIDE; 54 ui::DialogButton button) const OVERRIDE;
55 virtual bool Cancel() OVERRIDE; 55 virtual bool Cancel() OVERRIDE;
56 virtual bool Accept() OVERRIDE; 56 virtual bool Accept() OVERRIDE;
57 57
58 // Overridden from views::WidgetDelegate: 58 // Overridden from views::WidgetDelegate:
59 virtual base::string16 GetWindowTitle() const OVERRIDE; 59 virtual base::string16 GetWindowTitle() const OVERRIDE;
60 virtual void DeleteDelegate() OVERRIDE; 60 virtual void DeleteDelegate() OVERRIDE;
61 virtual ui::ModalType GetModalType() const OVERRIDE; 61 virtual ui::ModalType GetModalType() const OVERRIDE;
62 virtual views::View* GetContentsView() OVERRIDE; 62 virtual views::View* GetContentsView() OVERRIDE;
63 virtual views::Widget* GetWidget() OVERRIDE; 63 virtual views::Widget* GetWidget() OVERRIDE;
64 virtual const views::Widget* GetWidget() const OVERRIDE; 64 virtual const views::Widget* GetWidget() const OVERRIDE;
65 65
66 // Overridden from MessagePumpDispatcher:
67 virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE;
68
69 private: 66 private:
70 friend class base::RefCounted<SimpleMessageBoxViews>; 67 friend class base::RefCounted<SimpleMessageBoxViews>;
71 virtual ~SimpleMessageBoxViews(); 68 virtual ~SimpleMessageBoxViews();
72 69
70 // This terminates the nested message-loop.
71 void Done();
72
73 const base::string16 window_title_; 73 const base::string16 window_title_;
74 const MessageBoxType type_; 74 const MessageBoxType type_;
75 base::string16 yes_text_; 75 base::string16 yes_text_;
76 base::string16 no_text_; 76 base::string16 no_text_;
77 MessageBoxResult result_; 77 MessageBoxResult result_;
78 views::MessageBoxView* message_box_view_; 78 views::MessageBoxView* message_box_view_;
79 79
80 // Set to false as soon as the user clicks a dialog button; this tells the
81 // dispatcher we're done.
82 bool should_show_dialog_;
83
84 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews); 80 DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
85 }; 81 };
86 82
87 //////////////////////////////////////////////////////////////////////////////// 83 ////////////////////////////////////////////////////////////////////////////////
88 // SimpleMessageBoxViews, public: 84 // SimpleMessageBoxViews, public:
89 85
90 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title, 86 SimpleMessageBoxViews::SimpleMessageBoxViews(const base::string16& title,
91 const base::string16& message, 87 const base::string16& message,
92 MessageBoxType type, 88 MessageBoxType type,
93 const base::string16& yes_text, 89 const base::string16& yes_text,
94 const base::string16& no_text) 90 const base::string16& no_text)
95 : window_title_(title), 91 : window_title_(title),
96 type_(type), 92 type_(type),
97 yes_text_(yes_text), 93 yes_text_(yes_text),
98 no_text_(no_text), 94 no_text_(no_text),
99 result_(MESSAGE_BOX_RESULT_NO), 95 result_(MESSAGE_BOX_RESULT_NO),
100 message_box_view_(new views::MessageBoxView( 96 message_box_view_(new views::MessageBoxView(
101 views::MessageBoxView::InitParams(message))), 97 views::MessageBoxView::InitParams(message))) {
102 should_show_dialog_(true) {
103 AddRef(); 98 AddRef();
104 99
105 if (yes_text_.empty()) { 100 if (yes_text_.empty()) {
106 if (type_ == MESSAGE_BOX_TYPE_QUESTION) 101 if (type_ == MESSAGE_BOX_TYPE_QUESTION)
107 yes_text_ = 102 yes_text_ =
108 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); 103 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL);
109 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL) 104 else if (type_ == MESSAGE_BOX_TYPE_OK_CANCEL)
110 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); 105 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
111 else 106 else
112 yes_text_ = l10n_util::GetStringUTF16(IDS_OK); 107 yes_text_ = l10n_util::GetStringUTF16(IDS_OK);
(...skipping 18 matching lines...) Expand all
131 } 126 }
132 127
133 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel( 128 base::string16 SimpleMessageBoxViews::GetDialogButtonLabel(
134 ui::DialogButton button) const { 129 ui::DialogButton button) const {
135 if (button == ui::DIALOG_BUTTON_CANCEL) 130 if (button == ui::DIALOG_BUTTON_CANCEL)
136 return no_text_; 131 return no_text_;
137 return yes_text_; 132 return yes_text_;
138 } 133 }
139 134
140 bool SimpleMessageBoxViews::Cancel() { 135 bool SimpleMessageBoxViews::Cancel() {
141 should_show_dialog_= false;
142 result_ = MESSAGE_BOX_RESULT_NO; 136 result_ = MESSAGE_BOX_RESULT_NO;
137 Done();
143 return true; 138 return true;
144 } 139 }
145 140
146 bool SimpleMessageBoxViews::Accept() { 141 bool SimpleMessageBoxViews::Accept() {
147 should_show_dialog_ = false;
148 result_ = MESSAGE_BOX_RESULT_YES; 142 result_ = MESSAGE_BOX_RESULT_YES;
143 Done();
149 return true; 144 return true;
150 } 145 }
151 146
152 base::string16 SimpleMessageBoxViews::GetWindowTitle() const { 147 base::string16 SimpleMessageBoxViews::GetWindowTitle() const {
153 return window_title_; 148 return window_title_;
154 } 149 }
155 150
156 void SimpleMessageBoxViews::DeleteDelegate() { 151 void SimpleMessageBoxViews::DeleteDelegate() {
157 Release(); 152 Release();
158 } 153 }
159 154
160 ui::ModalType SimpleMessageBoxViews::GetModalType() const { 155 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
161 return ui::MODAL_TYPE_WINDOW; 156 return ui::MODAL_TYPE_WINDOW;
162 } 157 }
163 158
164 views::View* SimpleMessageBoxViews::GetContentsView() { 159 views::View* SimpleMessageBoxViews::GetContentsView() {
165 return message_box_view_; 160 return message_box_view_;
166 } 161 }
167 162
168 views::Widget* SimpleMessageBoxViews::GetWidget() { 163 views::Widget* SimpleMessageBoxViews::GetWidget() {
169 return message_box_view_->GetWidget(); 164 return message_box_view_->GetWidget();
170 } 165 }
171 166
172 const views::Widget* SimpleMessageBoxViews::GetWidget() const { 167 const views::Widget* SimpleMessageBoxViews::GetWidget() const {
173 return message_box_view_->GetWidget(); 168 return message_box_view_->GetWidget();
174 } 169 }
175 170
176 uint32_t SimpleMessageBoxViews::Dispatch(const base::NativeEvent& event) {
177 uint32_t action = POST_DISPATCH_PERFORM_DEFAULT;
178 if (!should_show_dialog_)
179 action |= POST_DISPATCH_QUIT_LOOP;
180 return action;
181 }
182
183 //////////////////////////////////////////////////////////////////////////////// 171 ////////////////////////////////////////////////////////////////////////////////
184 // SimpleMessageBoxViews, private: 172 // SimpleMessageBoxViews, private:
185 173
186 SimpleMessageBoxViews::~SimpleMessageBoxViews() { 174 SimpleMessageBoxViews::~SimpleMessageBoxViews() {
187 } 175 }
188 176
189 #if defined(OS_WIN) 177 #if defined(OS_WIN)
190 UINT GetMessageBoxFlagsFromType(MessageBoxType type) { 178 UINT GetMessageBoxFlagsFromType(MessageBoxType type) {
191 UINT flags = MB_SETFOREGROUND; 179 UINT flags = MB_SETFOREGROUND;
192 switch (type) { 180 switch (type) {
193 case MESSAGE_BOX_TYPE_INFORMATION: 181 case MESSAGE_BOX_TYPE_INFORMATION:
194 return flags | MB_OK | MB_ICONINFORMATION; 182 return flags | MB_OK | MB_ICONINFORMATION;
195 case MESSAGE_BOX_TYPE_WARNING: 183 case MESSAGE_BOX_TYPE_WARNING:
196 return flags | MB_OK | MB_ICONWARNING; 184 return flags | MB_OK | MB_ICONWARNING;
197 case MESSAGE_BOX_TYPE_QUESTION: 185 case MESSAGE_BOX_TYPE_QUESTION:
198 return flags | MB_YESNO | MB_ICONQUESTION; 186 return flags | MB_YESNO | MB_ICONQUESTION;
199 case MESSAGE_BOX_TYPE_OK_CANCEL: 187 case MESSAGE_BOX_TYPE_OK_CANCEL:
200 return flags | MB_OKCANCEL | MB_ICONWARNING; 188 return flags | MB_OKCANCEL | MB_ICONWARNING;
201 } 189 }
202 NOTREACHED(); 190 NOTREACHED();
203 return flags | MB_OK | MB_ICONWARNING; 191 return flags | MB_OK | MB_ICONWARNING;
204 } 192 }
205 #endif 193 #endif
206 194
195 void SimpleMessageBoxViews::Done() {
196 // The nested-loop is started from the parent's dispatcher client (if there is
197 // one), otherwise it's started from the widget's own window's dispatcher
198 // client. Make sure the termination of the nested loop happens from the
199 // correct dispatcher client.
200 aura::Window* window = GetWidget()->GetNativeView();
201 aura::Window* parent = views::corewm::GetTransientParent(window);
202 aura::client::DispatcherClient* client = NULL;
203 if (parent)
204 client = aura::client::GetDispatcherClient(parent->GetRootWindow());
205 if (!client)
206 client = aura::client::GetDispatcherClient(window->GetRootWindow());
207 client->QuitNestedMessageLoop();
208 }
209
207 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent, 210 MessageBoxResult ShowMessageBoxImpl(gfx::NativeWindow parent,
208 const base::string16& title, 211 const base::string16& title,
209 const base::string16& message, 212 const base::string16& message,
210 MessageBoxType type, 213 MessageBoxType type,
211 const base::string16& yes_text, 214 const base::string16& yes_text,
212 const base::string16& no_text) { 215 const base::string16& no_text) {
213 #if defined(OS_WIN) 216 #if defined(OS_WIN)
214 // GPU-based dialogs can't be used early on; fallback to a Windows MessageBox. 217 // GPU-based dialogs can't be used early on; fallback to a Windows MessageBox.
215 if (!ui::ContextFactory::GetInstance()) { 218 if (!ui::ContextFactory::GetInstance()) {
216 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message, 219 int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
(...skipping 10 matching lines...) Expand all
227 aura::Window* anchor = parent; 230 aura::Window* anchor = parent;
228 aura::client::DispatcherClient* client = anchor ? 231 aura::client::DispatcherClient* client = anchor ?
229 aura::client::GetDispatcherClient(anchor->GetRootWindow()) : NULL; 232 aura::client::GetDispatcherClient(anchor->GetRootWindow()) : NULL;
230 if (!client) { 233 if (!client) {
231 // Use the widget's window itself so that the message loop 234 // Use the widget's window itself so that the message loop
232 // exists when the dialog is closed by some other means than 235 // exists when the dialog is closed by some other means than
233 // |Cancel| or |Accept|. 236 // |Cancel| or |Accept|.
234 anchor = dialog->GetWidget()->GetNativeWindow(); 237 anchor = dialog->GetWidget()->GetNativeWindow();
235 client = aura::client::GetDispatcherClient(anchor->GetRootWindow()); 238 client = aura::client::GetDispatcherClient(anchor->GetRootWindow());
236 } 239 }
237 client->RunWithDispatcher(dialog.get(), anchor); 240 client->RunWithDispatcher(NULL, anchor);
238 return dialog->result(); 241 return dialog->result();
239 } 242 }
240 243
241 } // namespace 244 } // namespace
242 245
243 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent, 246 MessageBoxResult ShowMessageBox(gfx::NativeWindow parent,
244 const base::string16& title, 247 const base::string16& title,
245 const base::string16& message, 248 const base::string16& message,
246 MessageBoxType type) { 249 MessageBoxType type) {
247 return ShowMessageBoxImpl( 250 return ShowMessageBoxImpl(
248 parent, title, message, type, base::string16(), base::string16()); 251 parent, title, message, type, base::string16(), base::string16());
249 } 252 }
250 253
251 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent, 254 MessageBoxResult ShowMessageBoxWithButtonText(gfx::NativeWindow parent,
252 const base::string16& title, 255 const base::string16& title,
253 const base::string16& message, 256 const base::string16& message,
254 const base::string16& yes_text, 257 const base::string16& yes_text,
255 const base::string16& no_text) { 258 const base::string16& no_text) {
256 return ShowMessageBoxImpl( 259 return ShowMessageBoxImpl(
257 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text); 260 parent, title, message, MESSAGE_BOX_TYPE_QUESTION, yes_text, no_text);
258 } 261 }
259 262
260 } // namespace chrome 263 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/first_run_dialog.cc ('k') | ui/aura/client/dispatcher_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698