OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/controls/menu/menu_message_loop_aura.h" | 5 #include "ui/views/controls/menu/menu_message_loop_aura.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <windowsx.h> | 8 #include <windowsx.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 clone.set_root_location(root_loc); | 123 clone.set_root_location(root_loc); |
124 root->GetHost()->dispatcher()->RepostEvent(clone); | 124 root->GetHost()->dispatcher()->RepostEvent(clone); |
125 } | 125 } |
126 | 126 |
127 void MenuMessageLoopAura::Run(MenuController* controller, | 127 void MenuMessageLoopAura::Run(MenuController* controller, |
128 Widget* owner, | 128 Widget* owner, |
129 bool nested_menu) { | 129 bool nested_menu) { |
130 // |owner_| may be NULL. | 130 // |owner_| may be NULL. |
131 owner_ = owner; | 131 owner_ = owner; |
132 aura::Window* root = GetOwnerRootWindow(owner_); | 132 aura::Window* root = GetOwnerRootWindow(owner_); |
| 133 // It is possible for the same MenuMessageLoopAura to start a nested |
| 134 // message-loop while it is already running a nested loop. So make sure the |
| 135 // quit-closure gets reset to the outer loop's quit-closure once the innermost |
| 136 // loop terminates. |
| 137 base::AutoReset<base::Closure> reset_quit_closure(&message_loop_quit_, |
| 138 base::Closure()); |
133 | 139 |
134 #if defined(OS_WIN) | 140 #if defined(OS_WIN) |
135 internal::MenuMessagePumpDispatcher nested_dispatcher(controller); | 141 internal::MenuMessagePumpDispatcher nested_dispatcher(controller); |
136 if (root) { | 142 if (root) { |
137 scoped_ptr<ActivationChangeObserverImpl> observer; | 143 scoped_ptr<ActivationChangeObserverImpl> observer; |
138 if (!nested_menu) | 144 if (!nested_menu) |
139 observer.reset(new ActivationChangeObserverImpl(controller, root)); | 145 observer.reset(new ActivationChangeObserverImpl(controller, root)); |
140 aura::client::GetDispatcherClient(root) | 146 aura::client::DispatcherRunLoop run_loop( |
141 ->RunWithDispatcher(&nested_dispatcher); | 147 aura::client::GetDispatcherClient(root), &nested_dispatcher); |
| 148 message_loop_quit_ = run_loop.QuitClosure(); |
| 149 run_loop.Run(); |
142 } else { | 150 } else { |
143 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); | 151 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); |
144 base::MessageLoop::ScopedNestableTaskAllower allow(loop); | 152 base::MessageLoop::ScopedNestableTaskAllower allow(loop); |
145 base::RunLoop run_loop(&nested_dispatcher); | 153 base::RunLoop run_loop(&nested_dispatcher); |
| 154 message_loop_quit_ = run_loop.QuitClosure(); |
146 run_loop.Run(); | 155 run_loop.Run(); |
147 } | 156 } |
148 #else | 157 #else |
149 internal::MenuEventDispatcher event_dispatcher(controller); | 158 internal::MenuEventDispatcher event_dispatcher(controller); |
150 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = | 159 scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = |
151 nested_dispatcher_.Pass(); | 160 nested_dispatcher_.Pass(); |
152 if (ui::PlatformEventSource::GetInstance()) { | 161 if (ui::PlatformEventSource::GetInstance()) { |
153 nested_dispatcher_ = | 162 nested_dispatcher_ = |
154 ui::PlatformEventSource::GetInstance()->OverrideDispatcher( | 163 ui::PlatformEventSource::GetInstance()->OverrideDispatcher( |
155 &event_dispatcher); | 164 &event_dispatcher); |
156 } | 165 } |
157 if (root) { | 166 if (root) { |
158 scoped_ptr<ActivationChangeObserverImpl> observer; | 167 scoped_ptr<ActivationChangeObserverImpl> observer; |
159 if (!nested_menu) | 168 if (!nested_menu) |
160 observer.reset(new ActivationChangeObserverImpl(controller, root)); | 169 observer.reset(new ActivationChangeObserverImpl(controller, root)); |
161 aura::client::GetDispatcherClient(root)->RunWithDispatcher(NULL); | 170 aura::client::DispatcherRunLoop run_loop( |
| 171 aura::client::GetDispatcherClient(root), NULL); |
| 172 message_loop_quit_ = run_loop.QuitClosure(); |
| 173 run_loop.Run(); |
162 } else { | 174 } else { |
163 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); | 175 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); |
164 base::MessageLoop::ScopedNestableTaskAllower allow(loop); | 176 base::MessageLoop::ScopedNestableTaskAllower allow(loop); |
165 base::RunLoop run_loop; | 177 base::RunLoop run_loop; |
| 178 message_loop_quit_ = run_loop.QuitClosure(); |
166 run_loop.Run(); | 179 run_loop.Run(); |
167 } | 180 } |
168 nested_dispatcher_ = old_dispatcher.Pass(); | 181 nested_dispatcher_ = old_dispatcher.Pass(); |
169 #endif | 182 #endif |
170 } | 183 } |
171 | 184 |
172 bool MenuMessageLoopAura::ShouldQuitNow() const { | 185 bool MenuMessageLoopAura::ShouldQuitNow() const { |
173 aura::Window* root = GetOwnerRootWindow(owner_); | 186 aura::Window* root = GetOwnerRootWindow(owner_); |
174 return !aura::client::GetDragDropClient(root) || | 187 return !aura::client::GetDragDropClient(root) || |
175 !aura::client::GetDragDropClient(root)->IsDragDropInProgress(); | 188 !aura::client::GetDragDropClient(root)->IsDragDropInProgress(); |
176 } | 189 } |
177 | 190 |
178 void MenuMessageLoopAura::QuitNow() { | 191 void MenuMessageLoopAura::QuitNow() { |
179 if (owner_) { | 192 CHECK(!message_loop_quit_.is_null()); |
180 // It's safe to invoke QuitNestedMessageLoop() multiple times, it only | 193 message_loop_quit_.Run(); |
181 // effects the current loop. | |
182 aura::Window* root = owner_->GetNativeWindow()->GetRootWindow(); | |
183 aura::client::GetDispatcherClient(root)->QuitNestedMessageLoop(); | |
184 } else { | |
185 base::MessageLoop::current()->QuitNow(); | |
186 } | |
187 // Restore the previous dispatcher. | 194 // Restore the previous dispatcher. |
188 nested_dispatcher_.reset(); | 195 nested_dispatcher_.reset(); |
189 } | 196 } |
190 | 197 |
191 void MenuMessageLoopAura::ClearOwner() { | 198 void MenuMessageLoopAura::ClearOwner() { |
192 owner_ = NULL; | 199 owner_ = NULL; |
193 } | 200 } |
194 | 201 |
195 } // namespace views | 202 } // namespace views |
OLD | NEW |