Index: services/ui/ws/event_targeter.cc |
diff --git a/services/ui/ws/event_targeter.cc b/services/ui/ws/event_targeter.cc |
index 9329b4b536b4726e948574e44ecb88e1df6513b3..4ed9475d8dd6ce1fc3401dd63e95a6f52007f918 100644 |
--- a/services/ui/ws/event_targeter.cc |
+++ b/services/ui/ws/event_targeter.cc |
@@ -4,6 +4,8 @@ |
#include "services/ui/ws/event_targeter.h" |
+#include "base/command_line.h" |
+#include "base/task_scheduler/post_task.h" |
#include "services/ui/ws/event_dispatcher_delegate.h" |
#include "services/ui/ws/modal_window_controller.h" |
#include "services/ui/ws/window_finder.h" |
@@ -13,20 +15,78 @@ |
namespace ui { |
namespace ws { |
+EventTargeter::HitTestRequest::HitTestRequest(const gfx::Point& location, |
+ const int64_t display_id, |
+ HitTestCallback callback) |
+ : hittest_location(location), |
+ hittest_display_id(display_id), |
+ hittest_callback(std::move(callback)) {} |
+ |
+EventTargeter::HitTestRequest::~HitTestRequest() {} |
+ |
EventTargeter::EventTargeter(EventDispatcherDelegate* event_dispatcher_delegate, |
ModalWindowController* modal_window_controller) |
: event_dispatcher_delegate_(event_dispatcher_delegate), |
- modal_window_controller_(modal_window_controller) {} |
+ modal_window_controller_(modal_window_controller), |
+ hittest_in_flight_(false), |
+ weak_ptr_factory_(this) {} |
EventTargeter::~EventTargeter() {} |
-PointerTarget EventTargeter::PointerTargetForEvent( |
- const ui::LocatedEvent& event, |
- int64_t* display_id) { |
+void EventTargeter::PointerTargetForEvent( |
+ const ui::PointerEvent& event, |
+ const int64_t display_id, |
+ PointerTargetForEventCallback callback) { |
+ target_callback_ = std::move(callback); |
+ FindDeepestVisibleWindowForEvents( |
+ event.root_location(), display_id, |
+ base::BindOnce(&EventTargeter::PointerTargetForEventOnFoundWindow, |
+ weak_ptr_factory_.GetWeakPtr(), event)); |
+} |
+ |
+void EventTargeter::FindDeepestVisibleWindowForEvents( |
+ const gfx::Point& location, |
+ const int64_t display_id, |
+ HitTestCallback callback) { |
+ if (IsHitTestInFlight()) { |
+ std::unique_ptr<HitTestRequest> hittest_request = |
+ base::MakeUnique<HitTestRequest>(location, display_id, |
+ std::move(callback)); |
+ hittest_request_queue_.push(std::move(hittest_request)); |
+ return; |
+ } |
+ |
+ hittest_callback_ = std::move(callback); |
+ FindDeepestVisibleWindowForEventsImpl(location, display_id); |
+} |
+ |
+void EventTargeter::ProcessNextHittesetRequestFromQueue() { |
+ hittest_in_flight_ = false; |
+ if (hittest_request_queue_.empty()) { |
+ event_dispatcher_delegate_->ProcessNextEventFromQueue(); |
+ return; |
+ } |
+ std::unique_ptr<HitTestRequest> hittest_request = |
+ std::move(hittest_request_queue_.front()); |
+ |
+ hittest_request_queue_.pop(); |
+ hittest_callback_ = std::move(hittest_request->hittest_callback); |
+ FindDeepestVisibleWindowForEventsImpl(hittest_request->hittest_location, |
+ hittest_request->hittest_display_id); |
+} |
+ |
+bool EventTargeter::IsHitTestInFlight() const { |
+ if (hittest_in_flight_ || !hittest_request_queue_.empty()) |
+ return true; |
+ return false; |
+} |
+ |
+void EventTargeter::PointerTargetForEventOnFoundWindow( |
+ const ui::PointerEvent& event, |
+ const DeepestWindow& deepest_window, |
+ const gfx::Point& new_location, |
+ const int64_t new_display_id) { |
PointerTarget pointer_target; |
- gfx::Point event_root_location(event.root_location()); |
- DeepestWindow deepest_window = |
- FindDeepestVisibleWindowForEvents(&event_root_location, display_id); |
pointer_target.window = |
modal_window_controller_->GetTargetForWindow(deepest_window.window); |
pointer_target.is_mouse_event = event.IsMousePointerEvent(); |
@@ -34,16 +94,45 @@ PointerTarget EventTargeter::PointerTargetForEvent( |
deepest_window.window != pointer_target.window || |
!pointer_target.window || deepest_window.in_non_client_area; |
pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; |
- return pointer_target; |
+ base::ResetAndReturn(&target_callback_) |
+ .Run(pointer_target, deepest_window, new_location, new_display_id); |
+} |
+ |
+void EventTargeter::FindDeepestVisibleWindowForEventsImpl( |
+ const gfx::Point& location, |
+ const int64_t display_id) { |
+ // TODO(riajiang): After HitTestComponent is implemented, do synchronous |
+ // hit-test for most cases using shared memory and only ask Blink |
+ // asynchronously for hard cases. For now, assume all synchronous hit-tests |
+ // failed if the "enable-async-event-targeting" flag is turned on. |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ "enable-async-event-targeting")) { |
+ DCHECK(!hittest_in_flight_); |
+ hittest_in_flight_ = true; |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::BindOnce(&EventTargeter::FindDeepestVisibleWindowForEventsAsync, |
+ weak_ptr_factory_.GetWeakPtr(), location, display_id)); |
+ } else { |
+ FindDeepestVisibleWindowForEventsAsync(location, display_id); |
+ } |
} |
-DeepestWindow EventTargeter::FindDeepestVisibleWindowForEvents( |
- gfx::Point* location, |
- int64_t* display_id) { |
- ServerWindow* root = |
- event_dispatcher_delegate_->GetRootWindowContaining(location, display_id); |
- return root ? ui::ws::FindDeepestVisibleWindowForEvents(root, *location) |
- : DeepestWindow(); |
+void EventTargeter::FindDeepestVisibleWindowForEventsAsync( |
+ const gfx::Point& location, |
+ const int64_t display_id) { |
+ gfx::Point event_location(location); |
+ int64_t event_display_id = display_id; |
+ ServerWindow* root = event_dispatcher_delegate_->GetRootWindowContaining( |
+ &event_location, &event_display_id); |
+ if (root) { |
+ base::ResetAndReturn(&hittest_callback_) |
+ .Run(ui::ws::FindDeepestVisibleWindowForEvents(root, event_location), |
+ event_location, event_display_id); |
+ } else { |
+ base::ResetAndReturn(&hittest_callback_) |
+ .Run(DeepestWindow(), event_location, event_display_id); |
+ } |
} |
} // namespace ws |