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

Unified Diff: services/ui/ws/event_dispatcher.cc

Issue 2884463002: Make event-targeting asynchronous in window server. (Closed)
Patch Set: Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: services/ui/ws/event_dispatcher.cc
diff --git a/services/ui/ws/event_dispatcher.cc b/services/ui/ws/event_dispatcher.cc
index 83e8b37f26e8aafdacbec4f0fc45566195c18068..3101bbebbc2ed1e95fdba76553c137abada058b2 100644
--- a/services/ui/ws/event_dispatcher.cc
+++ b/services/ui/ws/event_dispatcher.cc
@@ -6,7 +6,9 @@
#include <algorithm>
+#include "base/command_line.h"
#include "base/memory/ptr_util.h"
+#include "base/task_scheduler/post_task.h"
#include "base/time/time.h"
#include "services/ui/ws/accelerator.h"
#include "services/ui/ws/drag_controller.h"
@@ -41,6 +43,14 @@ bool IsOnlyOneMouseButtonDown(int flags) {
////////////////////////////////////////////////////////////////////////////////
+EventDispatcher::HittestRequest::HittestRequest(gfx::Point location,
+ HittestCallback callback)
+ : hittest_location(location) {
+ hittest_callback = std::move(callback);
+}
+
+EventDispatcher::HittestRequest::~HittestRequest() {}
+
EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
: delegate_(delegate),
capture_window_(nullptr),
@@ -48,7 +58,8 @@ EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
modal_window_controller_(this),
mouse_button_down_(false),
mouse_cursor_source_window_(nullptr),
- mouse_cursor_in_non_client_area_(false) {}
+ mouse_cursor_in_non_client_area_(false),
+ hittest_in_flight_(false) {}
EventDispatcher::~EventDispatcher() {
SetMouseCursorSourceWindow(nullptr);
@@ -80,7 +91,7 @@ void EventDispatcher::SetMousePointerScreenLocation(
const gfx::Point& screen_location) {
DCHECK(pointer_targets_.empty());
mouse_pointer_last_location_ = screen_location;
- UpdateCursorProviderByLastKnownLocation();
+ UpdateCursorProviderByLastKnownLocation(base::Closure());
// Write our initial location back to our shared screen coordinate. This
// shouldn't cause problems because we already read the cursor before we
// process any events in views during window construction.
@@ -145,7 +156,7 @@ bool EventDispatcher::SetCaptureWindow(ServerWindow* window,
} else {
delegate_->ReleaseNativeCapture();
if (!mouse_button_down_)
- UpdateCursorProviderByLastKnownLocation();
+ UpdateCursorProviderByLastKnownLocation(base::Closure());
}
return true;
}
@@ -217,30 +228,25 @@ const ServerWindow* EventDispatcher::GetWindowForMouseCursor() const {
return window;
}
-void EventDispatcher::UpdateNonClientAreaForCurrentWindow() {
+void EventDispatcher::UpdateNonClientAreaForCurrentWindow(
+ const base::Closure& callback) {
if (mouse_cursor_source_window_) {
- DeepestWindow deepest_window =
- FindDeepestVisibleWindowForEvents(mouse_pointer_last_location_);
- if (deepest_window.window == mouse_cursor_source_window_) {
- mouse_cursor_in_non_client_area_ = mouse_cursor_source_window_
- ? deepest_window.in_non_client_area
- : false;
- }
+ FindDeepestVisibleWindowForEvents(
+ mouse_pointer_last_location_,
+ base::BindOnce(
+ &EventDispatcher::UpdateNonClientAreaForCurrentWindowOnFoundWindow,
+ base::Unretained(this), callback));
}
}
-void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
+void EventDispatcher::UpdateCursorProviderByLastKnownLocation(
+ const base::Closure& callback) {
if (!mouse_button_down_) {
- DeepestWindow deepest_window =
- FindDeepestVisibleWindowForEvents(mouse_pointer_last_location_);
- SetMouseCursorSourceWindow(deepest_window.window);
- if (mouse_cursor_source_window_) {
- mouse_cursor_in_non_client_area_ = deepest_window.in_non_client_area;
- } else {
- gfx::Point location = mouse_pointer_last_location_;
- SetMouseCursorSourceWindow(delegate_->GetRootWindowContaining(&location));
- mouse_cursor_in_non_client_area_ = true;
- }
+ FindDeepestVisibleWindowForEvents(
+ mouse_pointer_last_location_,
+ base::BindOnce(&EventDispatcher::
+ UpdateCursorProviderByLastKnownLocationOnFoundWindow,
+ base::Unretained(this), callback));
}
}
@@ -347,6 +353,16 @@ void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event,
void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) {
DCHECK(event.IsPointerEvent());
+ PointerTargetForEvent(
+ event, base::BindOnce(&EventDispatcher::ProcessPointerEventOnFoundTarget,
+ base::Unretained(this), event));
+}
+
+void EventDispatcher::ProcessPointerEventOnFoundTarget(
+ const ui::PointerEvent& event,
+ PointerTarget pointer_target_found) {
+ ProcessNextHittesetRequestFromQueue();
+
const bool is_mouse_event = event.IsMousePointerEvent();
if (is_mouse_event) {
@@ -370,8 +386,8 @@ void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) {
}
if (drag_controller_) {
- const PointerTarget target = PointerTargetForEvent(event);
- if (drag_controller_->DispatchPointerEvent(event, target.window))
+ if (drag_controller_->DispatchPointerEvent(event,
+ pointer_target_found.window))
return;
}
@@ -385,7 +401,7 @@ void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) {
if (!IsTrackingPointer(pointer_id) ||
!pointer_targets_[pointer_id].is_pointer_down) {
const bool any_pointers_down = AreAnyPointersDown();
- UpdateTargetForPointer(pointer_id, event);
+ UpdateTargetForPointer(pointer_id, event, pointer_target_found);
if (is_mouse_event)
SetMouseCursorSourceWindow(pointer_targets_[pointer_id].window);
@@ -412,7 +428,7 @@ void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) {
// before we perform dispatch because the Delegate is going to read this
// information from us.
if (is_pointer_going_up && is_mouse_event)
- UpdateCursorProviderByLastKnownLocation();
+ UpdateCursorProviderByLastKnownLocation(base::Closure());
DispatchToPointerTarget(pointer_targets_[pointer_id], event);
@@ -443,20 +459,21 @@ void EventDispatcher::StopTrackingPointer(int32_t pointer_id) {
UnobserveWindow(window);
}
-void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id,
- const ui::LocatedEvent& event) {
+void EventDispatcher::UpdateTargetForPointer(
+ int32_t pointer_id,
+ const ui::PointerEvent& event,
+ const PointerTarget& pointer_target_found) {
if (!IsTrackingPointer(pointer_id)) {
- StartTrackingPointer(pointer_id, PointerTargetForEvent(event));
+ StartTrackingPointer(pointer_id, pointer_target_found);
return;
}
- const PointerTarget pointer_target = PointerTargetForEvent(event);
- if (pointer_target.window == pointer_targets_[pointer_id].window &&
- pointer_target.in_nonclient_area ==
+ if (pointer_target_found.window == pointer_targets_[pointer_id].window &&
+ pointer_target_found.in_nonclient_area ==
pointer_targets_[pointer_id].in_nonclient_area) {
// The targets are the same, only set the down state to true if necessary.
// Down going to up is handled by ProcessLocatedEvent().
- if (pointer_target.is_pointer_down)
+ if (pointer_target_found.is_pointer_down)
pointer_targets_[pointer_id].is_pointer_down = true;
return;
}
@@ -475,14 +492,23 @@ void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id,
// Technically we're updating in place, but calling start then stop makes for
// simpler code.
StopTrackingPointer(pointer_id);
- StartTrackingPointer(pointer_id, pointer_target);
+ StartTrackingPointer(pointer_id, pointer_target_found);
}
-EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent(
- const ui::LocatedEvent& event) {
+void EventDispatcher::PointerTargetForEvent(
+ const ui::PointerEvent& event,
+ PointerTargetForEventCallback callback) {
+ FindDeepestVisibleWindowForEvents(
+ event.root_location(),
+ base::BindOnce(&EventDispatcher::PointerTargetForEventOnFoundWindow,
+ base::Unretained(this), event, std::move(callback)));
+}
+
+void EventDispatcher::PointerTargetForEventOnFoundWindow(
+ const ui::PointerEvent& event,
+ PointerTargetForEventCallback callback,
+ DeepestWindow deepest_window) {
PointerTarget pointer_target;
- DeepestWindow deepest_window =
- FindDeepestVisibleWindowForEvents(event.root_location());
pointer_target.window =
modal_window_controller_.GetTargetForWindow(deepest_window.window);
pointer_target.is_mouse_event = event.IsMousePointerEvent();
@@ -490,7 +516,7 @@ EventDispatcher::PointerTarget EventDispatcher::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;
+ std::move(callback).Run(pointer_target);
}
bool EventDispatcher::AreAnyPointersDown() const {
@@ -540,7 +566,7 @@ void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) {
// explicit capture.
delegate_->OnCaptureChanged(nullptr, window);
delegate_->ReleaseNativeCapture();
- UpdateCursorProviderByLastKnownLocation();
+ UpdateCursorProviderByLastKnownLocation(base::Closure());
return;
}
@@ -580,14 +606,92 @@ Accelerator* EventDispatcher::FindAccelerator(
return nullptr;
}
-DeepestWindow EventDispatcher::FindDeepestVisibleWindowForEvents(
- const gfx::Point& location) {
+void EventDispatcher::FindDeepestVisibleWindowForEvents(
+ const gfx::Point& location,
+ HittestCallback callback) {
+ if (hittest_in_flight_ || !hittest_request_queue_.empty()) {
+ std::unique_ptr<HittestRequest> hittest_request =
+ base::MakeUnique<HittestRequest>(location, std::move(callback));
+ hittest_request_queue_.push(std::move(hittest_request));
+ return;
+ }
+
+ FindDeepestVisibleWindowForEventsImpl(location, std::move(callback));
+}
+
+void EventDispatcher::FindDeepestVisibleWindowForEventsImpl(
+ const gfx::Point& location,
+ HittestCallback callback) {
+ // 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(&EventDispatcher::FindDeepestVisibleWindowForEventsAsync,
+ base::Unretained(this), location, std::move(callback)));
sky 2017/05/14 15:59:05 What guarantees this is valid by the time the call
riajiang 2017/05/15 18:34:41 As discussed, changed to use WeakPtrFactory.
+ } else {
+ FindDeepestVisibleWindowForEventsAsync(location, std::move(callback));
+ }
+}
+
+void EventDispatcher::FindDeepestVisibleWindowForEventsAsync(
+ const gfx::Point& location,
+ HittestCallback callback) {
gfx::Point relative_location(location);
- // For the case of no root.
ServerWindow* root = delegate_->GetRootWindowContaining(&relative_location);
- return root ? ui::ws::FindDeepestVisibleWindowForEvents(root,
- relative_location)
- : DeepestWindow();
+ if (root) {
+ std::move(callback).Run(
+ ui::ws::FindDeepestVisibleWindowForEvents(root, relative_location));
+ } else {
+ std::move(callback).Run(DeepestWindow());
+ }
+}
+
+void EventDispatcher::UpdateNonClientAreaForCurrentWindowOnFoundWindow(
+ const base::Closure& callback,
+ DeepestWindow deepest_window) {
+ ProcessNextHittesetRequestFromQueue();
+
+ if (deepest_window.window == mouse_cursor_source_window_) {
+ mouse_cursor_in_non_client_area_ =
+ mouse_cursor_source_window_ ? deepest_window.in_non_client_area : false;
+ }
+ if (callback)
+ callback.Run();
+}
+
+void EventDispatcher::UpdateCursorProviderByLastKnownLocationOnFoundWindow(
+ const base::Closure& callback,
+ DeepestWindow deepest_window) {
+ ProcessNextHittesetRequestFromQueue();
+
+ SetMouseCursorSourceWindow(deepest_window.window);
+ if (mouse_cursor_source_window_) {
+ mouse_cursor_in_non_client_area_ = deepest_window.in_non_client_area;
+ } else {
+ gfx::Point location = mouse_pointer_last_location_;
+ SetMouseCursorSourceWindow(delegate_->GetRootWindowContaining(&location));
+ mouse_cursor_in_non_client_area_ = true;
+ }
+ if (callback)
+ callback.Run();
+}
+
+void EventDispatcher::ProcessNextHittesetRequestFromQueue() {
+ hittest_in_flight_ = false;
+ if (hittest_request_queue_.empty())
+ return;
+ std::unique_ptr<HittestRequest> hittest_request =
+ std::move(hittest_request_queue_.front());
+ hittest_request_queue_.pop();
+ FindDeepestVisibleWindowForEventsImpl(
+ hittest_request->hittest_location,
+ std::move(hittest_request->hittest_callback));
}
void EventDispatcher::CancelImplicitCaptureExcept(ServerWindow* window,

Powered by Google App Engine
This is Rietveld 408576698