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

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

Issue 2884463002: Make event-targeting asynchronous in window server. (Closed)
Patch Set: std::move 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..898a30f8d8b4bff66340cd95a2873df58ca5edda 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(const gfx::Point& location,
+ HitTestCallback callback)
+ : hittest_location(location) {
+ hittest_callback = std::move(callback);
sky 2017/05/22 16:06:56 move to member initializer.
riajiang 2017/05/29 23:38:07 Done.
+}
+
+EventDispatcher::HitTestRequest::~HitTestRequest() {}
+
EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
: delegate_(delegate),
capture_window_(nullptr),
@@ -48,7 +58,9 @@ 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),
+ weak_ptr_factory_(this) {}
EventDispatcher::~EventDispatcher() {
SetMouseCursorSourceWindow(nullptr);
@@ -219,28 +231,21 @@ const ServerWindow* EventDispatcher::GetWindowForMouseCursor() const {
void EventDispatcher::UpdateNonClientAreaForCurrentWindow() {
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,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
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,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -308,6 +313,12 @@ void EventDispatcher::ProcessEvent(const ui::Event& event,
return;
}
+bool EventDispatcher::IsHitTestInFlight() const {
+ if (hittest_in_flight_ || !hittest_request_queue_.empty())
+ return true;
+ return false;
+}
+
void EventDispatcher::SetMouseCursorSourceWindow(ServerWindow* window) {
if (mouse_cursor_source_window_ == window)
return;
@@ -347,6 +358,16 @@ void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event,
void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) {
DCHECK(event.IsPointerEvent());
+ PointerTargetForEvent(
+ event, base::BindOnce(&EventDispatcher::ProcessPointerEventOnFoundTarget,
+ weak_ptr_factory_.GetWeakPtr(), 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 +391,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 +406,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);
@@ -443,20 +464,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 +497,24 @@ 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);
+}
+
+void EventDispatcher::PointerTargetForEvent(
+ const ui::PointerEvent& event,
+ PointerTargetForEventCallback callback) {
+ FindDeepestVisibleWindowForEvents(
+ event.root_location(),
+ base::BindOnce(&EventDispatcher::PointerTargetForEventOnFoundWindow,
+ weak_ptr_factory_.GetWeakPtr(), event,
+ std::move(callback)));
}
-EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent(
- const ui::LocatedEvent& event) {
+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 +522,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 {
@@ -580,14 +612,91 @@ Accelerator* EventDispatcher::FindAccelerator(
return nullptr;
}
-DeepestWindow EventDispatcher::FindDeepestVisibleWindowForEvents(
- const gfx::Point& location) {
+void EventDispatcher::FindDeepestVisibleWindowForEvents(
+ const gfx::Point& location,
+ HitTestCallback callback) {
+ if (IsHitTestInFlight()) {
+ 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,
+ weak_ptr_factory_.GetWeakPtr(), location,
+ std::move(callback)));
+ } 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(
+ 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;
+ }
+ delegate_->UpdateNativeCursorFromDispatcher();
+}
+
+void EventDispatcher::UpdateCursorProviderByLastKnownLocationOnFoundWindow(
+ 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;
+ }
+ delegate_->UpdateNativeCursorFromDispatcher();
+}
+
+void EventDispatcher::ProcessNextHittesetRequestFromQueue() {
+ hittest_in_flight_ = false;
+ if (hittest_request_queue_.empty()) {
+ delegate_->ProcessNextEventFromQueue();
+ 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