Index: ui/views/mus/platform_window_mus.cc |
diff --git a/ui/views/mus/platform_window_mus.cc b/ui/views/mus/platform_window_mus.cc |
index 4b72979b40ce92857c8d88346fcdc320a7a2eb10..f1d58a37dabfda16ce900e8ed835e42ad868bd28 100644 |
--- a/ui/views/mus/platform_window_mus.cc |
+++ b/ui/views/mus/platform_window_mus.cc |
@@ -4,6 +4,7 @@ |
#include "ui/views/mus/platform_window_mus.h" |
+#include "base/message_loop/message_loop.h" |
#include "build/build_config.h" |
#include "components/bitmap_uploader/bitmap_uploader.h" |
#include "components/mus/public/cpp/property_type_converters.h" |
@@ -14,11 +15,40 @@ |
#include "ui/platform_window/platform_window_delegate.h" |
#include "ui/views/mus/window_manager_connection.h" |
+using mus::mojom::EventResult; |
+ |
namespace views { |
namespace { |
+ |
static uint32_t accelerated_widget_count = 1; |
+// Acknowledges an input event immediately if a nested message loop starts. |
+// Needed because otherwise we appear unresponsive for the life of the nested |
+// message loop. |
+class EventAckNestingObserver : public base::MessageLoop::NestingObserver { |
+ public: |
+ explicit EventAckNestingObserver( |
+ std::unique_ptr<base::Callback<void(EventResult)>>* ack_callback) |
sky
2016/04/27 17:49:48
Did you consider making this take a std::unique_pt
James Cook
2016/04/27 18:11:14
Done.
|
+ : ack_callback_(ack_callback) { |
+ DCHECK(ack_callback_); |
+ } |
+ ~EventAckNestingObserver() override {} |
+ |
+ // base::MessageLoop::NestingObserver: |
+ void OnBeginNestedMessageLoop() override { |
+ if (*ack_callback_) { |
+ (*ack_callback_)->Run(EventResult::HANDLED); |
+ ack_callback_->reset(); // Signal that the event was ack'd. |
+ } |
+ } |
+ |
+ private: |
+ std::unique_ptr<base::Callback<void(EventResult)>>* ack_callback_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EventAckNestingObserver); |
+}; |
+ |
} // namespace |
PlatformWindowMus::PlatformWindowMus(ui::PlatformWindowDelegate* delegate, |
@@ -222,17 +252,29 @@ void PlatformWindowMus::OnRequestClose(mus::Window* window) { |
void PlatformWindowMus::OnWindowInputEvent( |
mus::Window* view, |
- const ui::Event& event, |
- std::unique_ptr<base::Callback<void(mus::mojom::EventResult)>>* |
- ack_callback) { |
- // It's possible dispatching the event will spin a nested message loop. Ack |
- // the callback now, otherwise we appear unresponsive for the life of the |
- // nested message loop. |
- (*ack_callback)->Run(mus::mojom::EventResult::HANDLED); |
- ack_callback->reset(); |
- // TODO(moshayedi): Avoid cloning after updating PlatformWindowDelegate to |
- // accept constant pointers. |
- delegate_->DispatchEvent(ui::Event::Clone(event).get()); |
+ const ui::Event& event_in, |
+ std::unique_ptr<base::Callback<void(EventResult)>>* ack_callback_in) { |
+ // Take ownership of the callback, indicating that we will handle it. |
+ std::unique_ptr<base::Callback<void(EventResult)>> ack_callback = |
+ std::move(*ack_callback_in); |
+ |
+ // If dispatching the event creates a nested message loop we need to ack the |
+ // event immediately. There might be multiple nested message loops; each one |
+ // needs its own observer. |
+ EventAckNestingObserver nesting_observer(&ack_callback); |
+ base::MessageLoop::current()->AddNestingObserver(&nesting_observer); |
+ |
+ std::unique_ptr<ui::Event> event = ui::Event::Clone(event_in); |
+ delegate_->DispatchEvent(event.get()); |
+ // NOTE: |this| may be deleted. |
+ |
+ base::MessageLoop::current()->RemoveNestingObserver(&nesting_observer); |
+ |
+ // If the callback wasn't already called by the message loop observer then |
+ // ack it with the handled state. |
+ if (ack_callback) |
+ ack_callback->Run(event->handled() ? EventResult::HANDLED |
+ : EventResult::UNHANDLED); |
} |
} // namespace views |