EventProcessor redispatch refactor
Add "GetNewEventSinkForEvent" for the case that event needs to be re-dispatched to different event sink. Bug: 1345952 Test: no functional change. All test should still pass Change-Id: Iec36a20730b452e8bf0917057ed6581cc4f92e3c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3823599 Reviewed-by: Scott Violet <sky@chromium.org> Commit-Queue: Mitsuru Oshima <oshima@chromium.org> Cr-Commit-Position: refs/heads/main@{#1120287}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
053f68e1d9
commit
3f1cf2aa0f
@ -12,7 +12,6 @@
|
||||
#include "ash/host/root_window_transformer.h"
|
||||
#include "base/check.h"
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "ui/aura/window.h"
|
||||
@ -37,37 +36,36 @@ class UnifiedEventTargeter : public aura::WindowTargeter {
|
||||
UnifiedEventTargeter& operator=(const UnifiedEventTargeter&) = delete;
|
||||
~UnifiedEventTargeter() override { delegate_ = nullptr; }
|
||||
|
||||
// aura::WindowTargeter:
|
||||
ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
|
||||
ui::Event* event) override {
|
||||
delegate_->SetCurrentEventTargeterSourceHost(nullptr);
|
||||
if (root == src_root_ && !event->target()) {
|
||||
delegate_->SetCurrentEventTargeterSourceHost(src_root_->GetHost());
|
||||
|
||||
if (event->IsLocatedEvent()) {
|
||||
ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
|
||||
located_event->ConvertLocationToTarget(
|
||||
static_cast<aura::Window*>(nullptr), dst_root_);
|
||||
}
|
||||
auto ptr = weak_ptr_factory_.GetWeakPtr();
|
||||
std::ignore =
|
||||
dst_root_->GetHost()->GetEventSink()->OnEventFromSource(event);
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
|
||||
// Reset the source host.
|
||||
delegate_->SetCurrentEventTargeterSourceHost(nullptr);
|
||||
|
||||
return nullptr;
|
||||
return root;
|
||||
} else {
|
||||
NOTREACHED() << "event type:" << event->type();
|
||||
return aura::WindowTargeter::FindTargetForEvent(root, event);
|
||||
}
|
||||
}
|
||||
ui::EventSink* GetNewEventSinkForEvent(const ui::EventTarget* current_root,
|
||||
ui::EventTarget* target,
|
||||
ui::Event* in_out_event) override {
|
||||
if (current_root == src_root_ && !in_out_event->target()) {
|
||||
delegate_->SetCurrentEventTargeterSourceHost(src_root_->GetHost());
|
||||
if (in_out_event->IsLocatedEvent()) {
|
||||
ui::LocatedEvent* located_event = in_out_event->AsLocatedEvent();
|
||||
located_event->ConvertLocationToTarget(
|
||||
static_cast<aura::Window*>(nullptr), dst_root_);
|
||||
}
|
||||
return dst_root_->GetHost()->GetEventSink();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
aura::Window* src_root_;
|
||||
aura::Window* dst_root_;
|
||||
AshWindowTreeHostDelegate* delegate_; // Not owned.
|
||||
base::WeakPtrFactory<UnifiedEventTargeter> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
AshWindowTreeHostUnified::AshWindowTreeHostUnified(
|
||||
|
@ -150,46 +150,11 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool WindowTargeter::ProcessEventIfTargetsDifferentRootWindow(
|
||||
Window* root_window,
|
||||
Window* target,
|
||||
ui::Event* event) {
|
||||
if (root_window->Contains(target))
|
||||
return false;
|
||||
|
||||
// |window| is the root window, but |target| is not a descendent of
|
||||
// |window|. So do not allow dispatching from here. Instead, dispatch the
|
||||
// event through the WindowEventDispatcher that owns |target|.
|
||||
Window* new_root = target->GetRootWindow();
|
||||
DCHECK(new_root);
|
||||
if (event->IsLocatedEvent()) {
|
||||
// The event has been transformed to be in |target|'s coordinate system.
|
||||
// But dispatching the event through the EventProcessor requires the event
|
||||
// to be in the host's coordinate system. So, convert the event to be in
|
||||
// the root's coordinate space, and then to the host's coordinate space by
|
||||
// applying the host's transform.
|
||||
ui::LocatedEvent* located_event = event->AsLocatedEvent();
|
||||
located_event->ConvertLocationToTarget(target, new_root);
|
||||
WindowTreeHost* window_tree_host = new_root->GetHost();
|
||||
located_event->UpdateForRootTransform(
|
||||
window_tree_host->GetRootTransform(),
|
||||
window_tree_host->GetRootTransformForLocalEventCoordinates());
|
||||
}
|
||||
std::ignore = new_root->GetHost()->GetEventSink()->OnEventFromSource(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
|
||||
ui::Event* event) {
|
||||
Window* window = static_cast<Window*>(root);
|
||||
Window* target = event->IsKeyEvent()
|
||||
? FindTargetForKeyEvent(window)
|
||||
: FindTargetForNonKeyEvent(window, event);
|
||||
if (target && !window->parent() &&
|
||||
ProcessEventIfTargetsDifferentRootWindow(window, target, event)) {
|
||||
return nullptr;
|
||||
}
|
||||
return target;
|
||||
return event->IsKeyEvent() ? FindTargetForKeyEvent(window)
|
||||
: FindTargetForNonKeyEvent(window, event);
|
||||
}
|
||||
|
||||
ui::EventTarget* WindowTargeter::FindNextBestTarget(
|
||||
@ -251,6 +216,38 @@ Window* WindowTargeter::FindTargetForLocatedEvent(Window* window,
|
||||
return FindTargetForLocatedEventRecursively(window, event);
|
||||
}
|
||||
|
||||
ui::EventSink* WindowTargeter::GetNewEventSinkForEvent(
|
||||
const ui::EventTarget* current_root,
|
||||
ui::EventTarget* target,
|
||||
ui::Event* in_out_event) {
|
||||
const aura::Window* root_window = static_cast<const Window*>(current_root);
|
||||
aura::Window* target_window = static_cast<Window*>(target);
|
||||
if (!target_window || root_window->parent() ||
|
||||
root_window->Contains(target_window)) {
|
||||
// no need to re-target.
|
||||
return nullptr;
|
||||
}
|
||||
// |window| is the root window, but |target| is not a descendent of
|
||||
// |window|. So do not allow dispatching from here. Instead, dispatch the
|
||||
// event through the WindowEventDispatcher that owns |target|.
|
||||
Window* new_root = target_window->GetRootWindow();
|
||||
DCHECK(new_root);
|
||||
if (in_out_event->IsLocatedEvent()) {
|
||||
// The event has been transformed to be in |target|'s coordinate system.
|
||||
// But dispatching the event through the EventProcessor requires the event
|
||||
// to be in the host's coordinate system. So, convert the event to be in
|
||||
// the root's coordinate space, and then to the host's coordinate space by
|
||||
// applying the host's transform.
|
||||
ui::LocatedEvent* located_event = in_out_event->AsLocatedEvent();
|
||||
located_event->ConvertLocationToTarget(target_window, new_root);
|
||||
WindowTreeHost* window_tree_host = new_root->GetHost();
|
||||
located_event->UpdateForRootTransform(
|
||||
window_tree_host->GetRootTransform(),
|
||||
window_tree_host->GetRootTransformForLocalEventCoordinates());
|
||||
}
|
||||
return new_root->GetHost()->GetEventSink();
|
||||
}
|
||||
|
||||
bool WindowTargeter::SubtreeCanAcceptEvent(
|
||||
Window* window,
|
||||
const ui::LocatedEvent& event) const {
|
||||
|
@ -78,18 +78,14 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
|
||||
Window* FindTargetInRootWindow(Window* root_window,
|
||||
const ui::LocatedEvent& event);
|
||||
|
||||
// If |target| is not a child of |root_window|, then converts |event| to
|
||||
// be relative to |root_window| and dispatches the event to |root_window|.
|
||||
// Returns false if the |target| is a child of |root_window|.
|
||||
bool ProcessEventIfTargetsDifferentRootWindow(Window* root_window,
|
||||
Window* target,
|
||||
ui::Event* event);
|
||||
|
||||
// ui::EventTargeter:
|
||||
ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
|
||||
ui::Event* event) override;
|
||||
ui::EventTarget* FindNextBestTarget(ui::EventTarget* previous_target,
|
||||
ui::Event* event) override;
|
||||
ui::EventSink* GetNewEventSinkForEvent(const ui::EventTarget* current_root,
|
||||
ui::EventTarget* target,
|
||||
ui::Event* in_out_event) override;
|
||||
|
||||
Window* FindTargetForKeyEvent(Window* root_window);
|
||||
|
||||
|
@ -47,39 +47,55 @@ EventDispatchDetails EventProcessor::OnEventFromSource(Event* event) {
|
||||
target = targeter->FindTargetForEvent(root, event_to_dispatch);
|
||||
}
|
||||
DCHECK(targeter);
|
||||
|
||||
// FindTargetForEvent may dispatch event, which may delete the event
|
||||
// processor.
|
||||
// processor or targeter.
|
||||
// TODO(crbug.com/1345952): Remove these returns and change this to DCHECK.
|
||||
if (!weak_this) {
|
||||
details.dispatcher_destroyed = true;
|
||||
return details;
|
||||
}
|
||||
if (!weak_targeter) {
|
||||
return details;
|
||||
}
|
||||
|
||||
while (target) {
|
||||
details = DispatchEvent(target, event_to_dispatch);
|
||||
|
||||
if (!dispatch_original_event) {
|
||||
if (event_to_dispatch->stopped_propagation())
|
||||
event->StopPropagation();
|
||||
else if (event_to_dispatch->handled())
|
||||
event->SetHandled();
|
||||
}
|
||||
|
||||
if (details.dispatcher_destroyed)
|
||||
return details;
|
||||
auto* new_event_sink =
|
||||
targeter->GetNewEventSinkForEvent(root, target, event_to_dispatch);
|
||||
|
||||
if (new_event_sink) {
|
||||
std::ignore = new_event_sink->OnEventFromSource(event_to_dispatch);
|
||||
if (!weak_this) {
|
||||
details.dispatcher_destroyed = true;
|
||||
return details;
|
||||
}
|
||||
} else {
|
||||
while (target) {
|
||||
details = DispatchEvent(target, event_to_dispatch);
|
||||
|
||||
if (details.target_destroyed || event->handled() || !target ||
|
||||
!weak_targeter) {
|
||||
break;
|
||||
if (!dispatch_original_event) {
|
||||
if (event_to_dispatch->stopped_propagation()) {
|
||||
event->StopPropagation();
|
||||
} else if (event_to_dispatch->handled()) {
|
||||
event->SetHandled();
|
||||
}
|
||||
}
|
||||
|
||||
if (details.dispatcher_destroyed) {
|
||||
return details;
|
||||
}
|
||||
|
||||
if (!weak_this) {
|
||||
details.dispatcher_destroyed = true;
|
||||
return details;
|
||||
}
|
||||
|
||||
if (details.target_destroyed || event->handled() || !target ||
|
||||
!weak_targeter) {
|
||||
break;
|
||||
}
|
||||
|
||||
DCHECK(targeter);
|
||||
target = targeter->FindNextBestTarget(target, event_to_dispatch);
|
||||
}
|
||||
|
||||
DCHECK(targeter);
|
||||
target = targeter->FindNextBestTarget(target, event_to_dispatch);
|
||||
}
|
||||
}
|
||||
OnEventProcessingFinished(event);
|
||||
|
@ -10,4 +10,11 @@ EventTargeter::EventTargeter() = default;
|
||||
|
||||
EventTargeter::~EventTargeter() = default;
|
||||
|
||||
EventSink* EventTargeter::GetNewEventSinkForEvent(
|
||||
const EventTarget* current_root,
|
||||
EventTarget* target,
|
||||
Event* in_out_event) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -11,6 +11,7 @@
|
||||
namespace ui {
|
||||
|
||||
class Event;
|
||||
class EventSink;
|
||||
class EventTarget;
|
||||
|
||||
class EVENTS_EXPORT EventTargeter {
|
||||
@ -36,6 +37,14 @@ class EVENTS_EXPORT EventTargeter {
|
||||
virtual EventTarget* FindNextBestTarget(EventTarget* previous_target,
|
||||
Event* event) = 0;
|
||||
|
||||
// Returns new event sink if the `in_out_event` should be dispatched to a
|
||||
// different sink. The event will be updated so that it can be dispatched to
|
||||
// the new sink correctly. Returns `nullptr` if the event do not have to be
|
||||
// redirected.
|
||||
virtual EventSink* GetNewEventSinkForEvent(const EventTarget* current_root,
|
||||
EventTarget* target,
|
||||
Event* in_out_event);
|
||||
|
||||
private:
|
||||
friend class EventProcessor;
|
||||
|
||||
|
Reference in New Issue
Block a user