Chromium Code Reviews| Index: services/ui/ws/event_targeter.cc |
| diff --git a/services/ui/ws/event_targeter.cc b/services/ui/ws/event_targeter.cc |
| index 7e1f3a4fc4c25374f83a066473075a3336698ac8..785faa750b0ed7db07f3405d1b8ad3b2406a1072 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_targeter_delegate.h" |
| #include "services/ui/ws/modal_window_controller.h" |
| #include "services/ui/ws/window_finder.h" |
| @@ -13,20 +15,63 @@ |
| namespace ui { |
| namespace ws { |
| +EventTargeter::HitTestRequest::HitTestRequest(const gfx::Point& location, |
| + int64_t display_id, |
| + HitTestCallback callback) |
| + : location(location), |
| + display_id(display_id), |
| + callback(std::move(callback)) {} |
| + |
| +EventTargeter::HitTestRequest::~HitTestRequest() {} |
| + |
| EventTargeter::EventTargeter(EventTargeterDelegate* event_targeter_delegate, |
| ModalWindowController* modal_window_controller) |
| : event_targeter_delegate_(event_targeter_delegate), |
| - modal_window_controller_(modal_window_controller) {} |
| + modal_window_controller_(modal_window_controller), |
| + hit_test_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, |
| + int64_t display_id, |
| + PointerTargetForEventCallback callback) { |
| + target_callback_ = std::move(callback); |
|
sky
2017/06/02 23:28:20
Why do you need target_callback_ and hit_test_call
riajiang
2017/06/05 23:56:15
I was passing them around (with std::move), but af
|
| + FindDeepestVisibleWindowForLocation( |
| + event.root_location(), display_id, |
| + base::BindOnce(&EventTargeter::PointerTargetForEventOnFoundWindow, |
| + weak_ptr_factory_.GetWeakPtr(), event)); |
| +} |
| + |
| +void EventTargeter::FindDeepestVisibleWindowForLocation( |
| + const gfx::Point& location, |
| + int64_t display_id, |
| + HitTestCallback callback) { |
| + if (IsHitTestInFlight()) { |
| + std::unique_ptr<HitTestRequest> hittest_request = |
| + base::MakeUnique<HitTestRequest>(location, display_id, |
| + std::move(callback)); |
| + hit_test_request_queue_.push(std::move(hittest_request)); |
| + return; |
| + } |
| + |
| + hit_test_callback_ = std::move(callback); |
| + FindDeepestVisibleWindowForLocationImpl(location, display_id); |
| +} |
| + |
| +bool EventTargeter::IsHitTestInFlight() const { |
| + if (hit_test_in_flight_ || !hit_test_request_queue_.empty()) |
|
sky
2017/06/02 23:28:20
Change this if to a return and get rid of the othe
riajiang
2017/06/05 23:56:15
Done.
|
| + return true; |
| + return false; |
| +} |
| + |
| +void EventTargeter::PointerTargetForEventOnFoundWindow( |
| + const ui::PointerEvent& event, |
| + const DeepestWindow& deepest_window, |
| + const gfx::Point& location_in_display, |
| + int64_t 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 +79,61 @@ 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, location_in_display, display_id); |
| +} |
| + |
| +void EventTargeter::FindDeepestVisibleWindowForLocationImpl( |
| + const gfx::Point& location, |
| + 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(!hit_test_in_flight_); |
| + hit_test_in_flight_ = true; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::BindOnce(&EventTargeter::FindDeepestVisibleWindowForLocationAsync, |
| + weak_ptr_factory_.GetWeakPtr(), location, display_id)); |
| + } else { |
| + FindDeepestVisibleWindowForLocationAsync(location, display_id); |
| + } |
| } |
| -DeepestWindow EventTargeter::FindDeepestVisibleWindowForEvents( |
| - gfx::Point* location, |
| - int64_t* display_id) { |
| - ServerWindow* root = |
| - event_targeter_delegate_->GetRootWindowContaining(location, display_id); |
| - return root ? ui::ws::FindDeepestVisibleWindowForEvents(root, *location) |
| - : DeepestWindow(); |
| +void EventTargeter::FindDeepestVisibleWindowForLocationAsync( |
| + const gfx::Point& location, |
| + int64_t display_id) { |
| + gfx::Point event_location(location); |
| + int64_t event_display_id = display_id; |
| + ServerWindow* root = event_targeter_delegate_->GetRootWindowContaining( |
| + &event_location, &event_display_id); |
| + if (root) { |
| + base::ResetAndReturn(&hit_test_callback_) |
| + .Run(ui::ws::FindDeepestVisibleWindowForLocation(root, event_location), |
| + event_location, event_display_id); |
| + } else { |
| + base::ResetAndReturn(&hit_test_callback_) |
| + .Run(DeepestWindow(), event_location, event_display_id); |
| + } |
| + ProcessNextHittesetRequestFromQueue(); |
| +} |
| + |
| +void EventTargeter::ProcessNextHittesetRequestFromQueue() { |
| + hit_test_in_flight_ = false; |
| + if (hit_test_request_queue_.empty()) { |
| + event_targeter_delegate_->ProcessNextEventFromQueue(); |
| + return; |
| + } |
| + |
| + std::unique_ptr<HitTestRequest> hittest_request = |
| + std::move(hit_test_request_queue_.front()); |
| + hit_test_request_queue_.pop(); |
| + hit_test_callback_ = std::move(hittest_request->callback); |
| + FindDeepestVisibleWindowForLocationImpl(hittest_request->location, |
| + hittest_request->display_id); |
| } |
| } // namespace ws |