Commit 344aea41 authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

chromeos: run callbacks if event is discarded by a rewriter

If an EventRewriter discards the event, callbacks should be run immediately.
Without this, the callback never gets run.

BUG=898658
TEST=covered by tests

Change-Id: Ia2644890750fe328506d4fce3f575f327c06cd1f
Reviewed-on: https://chromium-review.googlesource.com/c/1371216
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#615636}
parent 9d36bd38
...@@ -201,11 +201,12 @@ void AshWindowTreeHostPlatform::CommonInit() { ...@@ -201,11 +201,12 @@ void AshWindowTreeHostPlatform::CommonInit() {
SetSharedInputMethod(input_method_.get()); SetSharedInputMethod(input_method_.get());
} }
void AshWindowTreeHostPlatform::DispatchEventFromQueue(ui::Event* event) { ui::EventDispatchDetails AshWindowTreeHostPlatform::DispatchEventFromQueue(
ui::Event* event) {
TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent"); TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent");
if (event->IsLocatedEvent()) if (event->IsLocatedEvent())
TranslateLocatedEvent(static_cast<ui::LocatedEvent*>(event)); TranslateLocatedEvent(static_cast<ui::LocatedEvent*>(event));
SendEventToSink(event); return SendEventToSink(event);
} }
void AshWindowTreeHostPlatform::SetTapToClickPaused(bool state) { void AshWindowTreeHostPlatform::SetTapToClickPaused(bool state) {
......
...@@ -82,7 +82,7 @@ class ASH_EXPORT AshWindowTreeHostPlatform ...@@ -82,7 +82,7 @@ class ASH_EXPORT AshWindowTreeHostPlatform
ui::mojom::TextInputStatePtr state) override; ui::mojom::TextInputStatePtr state) override;
// ws::HostEventDispatcher: // ws::HostEventDispatcher:
void DispatchEventFromQueue(ui::Event* event) override; ui::EventDispatchDetails DispatchEventFromQueue(ui::Event* event) override;
private: private:
// All constructors call into this. // All constructors call into this.
......
...@@ -55,16 +55,17 @@ std::unique_ptr<HostEventQueue> EventQueue::RegisterHostEventDispatcher( ...@@ -55,16 +55,17 @@ std::unique_ptr<HostEventQueue> EventQueue::RegisterHostEventDispatcher(
} }
// static // static
void EventQueue::DispatchOrQueueEvent(WindowService* service, base::Optional<ui::EventDispatchDetails> EventQueue::DispatchOrQueueEvent(
aura::WindowTreeHost* window_tree_host, WindowService* service,
ui::Event* event, aura::WindowTreeHost* window_tree_host,
bool honor_rewriters) { ui::Event* event,
bool honor_rewriters) {
DCHECK(window_tree_host); DCHECK(window_tree_host);
HostEventQueue* host_event_queue = HostEventQueue* host_event_queue =
service->event_queue()->GetHostEventQueueForDisplay( service->event_queue()->GetHostEventQueueForDisplay(
window_tree_host->GetDisplayId()); window_tree_host->GetDisplayId());
DCHECK(host_event_queue); DCHECK(host_event_queue);
host_event_queue->DispatchOrQueueEvent(event, honor_rewriters); return host_event_queue->DispatchOrQueueEvent(event, honor_rewriters);
} }
bool EventQueue::ShouldQueueEvent(HostEventQueue* host_queue, bool EventQueue::ShouldQueueEvent(HostEventQueue* host_queue,
......
...@@ -26,6 +26,7 @@ class WindowTreeHost; ...@@ -26,6 +26,7 @@ class WindowTreeHost;
namespace ui { namespace ui {
class Event; class Event;
struct EventDispatchDetails;
} }
namespace ws { namespace ws {
...@@ -54,11 +55,13 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) EventQueue ...@@ -54,11 +55,13 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) EventQueue
// is true, the event is passed through EventRewriters first. Events received // is true, the event is passed through EventRewriters first. Events received
// from the platform go through EventRewriters, so generally // from the platform go through EventRewriters, so generally
// |honor_rewriters| should be true, remote injection may need to circumvent // |honor_rewriters| should be true, remote injection may need to circumvent
// that though. // that though. If the event was not queued, the return value contains the
static void DispatchOrQueueEvent(WindowService* service, // result of the event processing.
aura::WindowTreeHost* window_tree_host, static base::Optional<ui::EventDispatchDetails> DispatchOrQueueEvent(
ui::Event* event, WindowService* service,
bool honor_rewriters); aura::WindowTreeHost* window_tree_host,
ui::Event* event,
bool honor_rewriters);
// Returns true if |event| should be queued at this time. // Returns true if |event| should be queued at this time.
bool ShouldQueueEvent(HostEventQueue* host, const ui::Event& event); bool ShouldQueueEvent(HostEventQueue* host, const ui::Event& event);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
namespace ui { namespace ui {
class Event; class Event;
struct EventDispatchDetails;
} }
namespace ws { namespace ws {
...@@ -20,7 +21,7 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) HostEventDispatcher { ...@@ -20,7 +21,7 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) HostEventDispatcher {
// NOTE: as with other event dispatch related functions, the *caller* owns // NOTE: as with other event dispatch related functions, the *caller* owns
// |event|, but HostEventDispatcher may modify |event| as necessary (but not // |event|, but HostEventDispatcher may modify |event| as necessary (but not
// delete it). // delete it).
virtual void DispatchEventFromQueue(ui::Event* event) = 0; virtual ui::EventDispatchDetails DispatchEventFromQueue(ui::Event* event) = 0;
protected: protected:
virtual ~HostEventDispatcher() = default; virtual ~HostEventDispatcher() = default;
......
...@@ -25,22 +25,22 @@ HostEventQueue::~HostEventQueue() { ...@@ -25,22 +25,22 @@ HostEventQueue::~HostEventQueue() {
event_queue_->OnHostEventQueueDestroyed(this); event_queue_->OnHostEventQueueDestroyed(this);
} }
void HostEventQueue::DispatchOrQueueEvent(ui::Event* event, base::Optional<ui::EventDispatchDetails> HostEventQueue::DispatchOrQueueEvent(
bool honor_rewriters) { ui::Event* event,
if (event_queue_ && event_queue_->ShouldQueueEvent(this, *event)) bool honor_rewriters) {
if (event_queue_ && event_queue_->ShouldQueueEvent(this, *event)) {
event_queue_->QueueEvent(this, *event, honor_rewriters); event_queue_->QueueEvent(this, *event, honor_rewriters);
else return base::nullopt;
DispatchEventDontQueue(event, honor_rewriters); }
return DispatchEventDontQueue(event, honor_rewriters);
} }
void HostEventQueue::DispatchEventDontQueue(ui::Event* event, ui::EventDispatchDetails HostEventQueue::DispatchEventDontQueue(
bool honor_rewriters) { ui::Event* event,
if (honor_rewriters) { bool honor_rewriters) {
host_event_dispatcher_->DispatchEventFromQueue(event); if (honor_rewriters)
} else { return host_event_dispatcher_->DispatchEventFromQueue(event);
// No need to do anything with the result of sending the event. return window_tree_host_->event_sink()->OnEventFromSource(event);
ignore_result(window_tree_host_->event_sink()->OnEventFromSource(event));
}
} }
} // namespace ws } // namespace ws
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/component_export.h" #include "base/component_export.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h"
namespace aura { namespace aura {
class WindowTreeHost; class WindowTreeHost;
...@@ -15,6 +16,7 @@ class WindowTreeHost; ...@@ -15,6 +16,7 @@ class WindowTreeHost;
namespace ui { namespace ui {
class Event; class Event;
struct EventDispatchDetails;
} }
namespace ws { namespace ws {
...@@ -37,8 +39,12 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) HostEventQueue { ...@@ -37,8 +39,12 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) HostEventQueue {
~HostEventQueue(); ~HostEventQueue();
// If necessary, queues the event. If the event need not be queued, // If necessary, queues the event. If the event need not be queued,
// HostEventDispatcher::DispatchEventFromQueue() is called synchronously. // HostEventDispatcher::DispatchEventFromQueue() is called synchronously. If
void DispatchOrQueueEvent(ui::Event* event, bool honor_rewriters = true); // the event was not queued, the return value contains the result of the
// event processing.
base::Optional<ui::EventDispatchDetails> DispatchOrQueueEvent(
ui::Event* event,
bool honor_rewriters = true);
aura::WindowTreeHost* window_tree_host() { return window_tree_host_; } aura::WindowTreeHost* window_tree_host() { return window_tree_host_; }
...@@ -51,7 +57,8 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) HostEventQueue { ...@@ -51,7 +57,8 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) HostEventQueue {
// Dispatches an event directly, circumventing any queuing. This is private as // Dispatches an event directly, circumventing any queuing. This is private as
// it's only useful internally. // it's only useful internally.
void DispatchEventDontQueue(ui::Event* event, bool honor_rewriters); ui::EventDispatchDetails DispatchEventDontQueue(ui::Event* event,
bool honor_rewriters);
// Because of shutdown ordering, HostEventQueue may be deleted *after* // Because of shutdown ordering, HostEventQueue may be deleted *after*
// EventQueue. // EventQueue.
......
...@@ -57,13 +57,19 @@ void InjectedEventHandler::Inject(std::unique_ptr<ui::Event> event, ...@@ -57,13 +57,19 @@ void InjectedEventHandler::Inject(std::unique_ptr<ui::Event> event,
auto this_ref = weak_factory_.GetWeakPtr(); auto this_ref = weak_factory_.GetWeakPtr();
pre_target_register_ = std::make_unique<ScopedPreTargetRegister>( pre_target_register_ = std::make_unique<ScopedPreTargetRegister>(
window_service_->delegate()->GetGlobalEventTarget(), this); window_service_->delegate()->GetGlobalEventTarget(), this);
EventQueue::DispatchOrQueueEvent(window_service_, window_tree_host_, auto result = EventQueue::DispatchOrQueueEvent(window_service_,
event.get(), /* honors_rewriters */ true); window_tree_host_, event.get(),
/* honors_rewriters */ true);
if (!this_ref) if (!this_ref)
return; return;
// |pre_target_register_| needs to be a member to ensure it's destroyed // |pre_target_register_| needs to be a member to ensure it's destroyed
// if |this| is destroyed. // if |this| is destroyed.
pre_target_register_.reset(); pre_target_register_.reset();
if (result && result->event_discarded) {
DCHECK(!event_id_);
NotifyCallback();
}
} }
void InjectedEventHandler::NotifyCallback() { void InjectedEventHandler::NotifyCallback() {
......
...@@ -34,12 +34,13 @@ class WindowService; ...@@ -34,12 +34,13 @@ class WindowService;
// //
// Implementation note: an event may be handled in any of the following // Implementation note: an event may be handled in any of the following
// ways: // ways:
// . It may be dispatched to remote client. This is detected by way of // . It may be dispatched to a remote client. This is detected by way of
// OnWillSendEventToClient(). // OnWillSendEventToClient().
// . It may be handled locally. // . It may be handled locally.
// . It may be held and processed later on. This happens if pointer events are // . It may be held and processed later on. This happens if pointer events are
// being held if WindowEventDispatcher. See // being held if WindowEventDispatcher. See
// WindowEventDispatcher::HoldPointerMoves() for details. // WindowEventDispatcher::HoldPointerMoves() for details.
// . It may be discarded by an EventRewriter.
// For the case of the event being sent to a remote client this has to ensure // For the case of the event being sent to a remote client this has to ensure
// if the remote client, or WindowTreeHost is destroyed, then no ack is // if the remote client, or WindowTreeHost is destroyed, then no ack is
// received. // received.
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/test/window_event_dispatcher_test_api.h" #include "ui/aura/test/window_event_dispatcher_test_api.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_rewriter.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/platform_window_init_properties.h"
namespace ws { namespace ws {
...@@ -150,4 +153,59 @@ TEST(InjectedEventHandlerTest, HeldEvent) { ...@@ -150,4 +153,59 @@ TEST(InjectedEventHandlerTest, HeldEvent) {
EXPECT_TRUE(was_callback_run); EXPECT_TRUE(was_callback_run);
} }
class DiscardingEventRewriter : public ui::EventRewriter {
public:
DiscardingEventRewriter() = default;
~DiscardingEventRewriter() override = default;
bool got_rewrite_event() const { return got_rewrite_event_; }
// ui::EventRewriter:
ui::EventRewriteStatus RewriteEvent(
const ui::Event& event,
std::unique_ptr<ui::Event>* new_event) override {
got_rewrite_event_ = true;
return ui::EVENT_REWRITE_DISCARD;
}
ui::EventRewriteStatus NextDispatchEvent(
const ui::Event& last_event,
std::unique_ptr<ui::Event>* new_event) override {
return ui::EVENT_REWRITE_DISPATCH_ANOTHER;
}
private:
bool got_rewrite_event_ = false;
DISALLOW_COPY_AND_ASSIGN(DiscardingEventRewriter);
};
TEST(InjectedEventHandlerTest, RewriterDiscards) {
// Create a single window and give it focus.
DiscardingEventRewriter rewriter;
WindowServiceTestSetup test_setup;
test_setup.aura_test_helper()->root_window()->GetHost()->AddEventRewriter(
&rewriter);
aura::Window* top_level =
test_setup.window_tree_test_helper()->NewTopLevelWindow();
ASSERT_TRUE(top_level);
top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
top_level->Show();
top_level->Focus();
EXPECT_TRUE(top_level->HasFocus());
// Dispatch an event. Because the rewriter discards the event, the callback
// should be run immediately.
bool was_callback_run = false;
InjectedEventHandler injected_event_handler(test_setup.service(),
test_setup.root()->GetHost());
ui::KeyEvent char_event('A', ui::VKEY_A, ui::DomCode::NONE, 0);
injected_event_handler.Inject(
ui::Event::Clone(char_event),
base::BindOnce([](bool* was_run) { *was_run = true; },
&was_callback_run));
EXPECT_TRUE(was_callback_run);
EXPECT_TRUE(rewriter.got_rewrite_event());
}
} // namespace ws } // namespace ws
...@@ -18,9 +18,9 @@ TestHostEventDispatcher::TestHostEventDispatcher( ...@@ -18,9 +18,9 @@ TestHostEventDispatcher::TestHostEventDispatcher(
TestHostEventDispatcher::~TestHostEventDispatcher() = default; TestHostEventDispatcher::~TestHostEventDispatcher() = default;
void TestHostEventDispatcher::DispatchEventFromQueue(ui::Event* event) { ui::EventDispatchDetails TestHostEventDispatcher::DispatchEventFromQueue(
ignore_result( ui::Event* event) {
ui::EventSourceTestApi(window_tree_host_).SendEventToSink(event)); return ui::EventSourceTestApi(window_tree_host_).SendEventToSink(event);
} }
} // namespace ws } // namespace ws
...@@ -21,7 +21,7 @@ class TestHostEventDispatcher : public HostEventDispatcher { ...@@ -21,7 +21,7 @@ class TestHostEventDispatcher : public HostEventDispatcher {
~TestHostEventDispatcher() override; ~TestHostEventDispatcher() override;
// HostEventDispatcher: // HostEventDispatcher:
void DispatchEventFromQueue(ui::Event* event) override; ui::EventDispatchDetails DispatchEventFromQueue(ui::Event* event) override;
private: private:
aura::WindowTreeHost* window_tree_host_; aura::WindowTreeHost* window_tree_host_;
......
...@@ -21,11 +21,6 @@ ...@@ -21,11 +21,6 @@
-SelectToSpeakTest.SmoothlyReadsAcrossMultipleLines -SelectToSpeakTest.SmoothlyReadsAcrossMultipleLines
-SelectToSpeakTest.SpeakStatusTray -SelectToSpeakTest.SpeakStatusTray
-SelectToSpeakTest.WorksWithStickyKeys -SelectToSpeakTest.WorksWithStickyKeys
-StickyKeysBrowserTest.CtrlClickHomeButton
-StickyKeysBrowserTest.OpenNewTabs
-StickyKeysBrowserTest.OpenTrayMenu
-StickyKeysBrowserTest.OverlayShown
-StickyKeysBrowserTest.SearchLeftOmnibox
-TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxNextTabRecovery/0 -TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxNextTabRecovery/0
-TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxNextTabRecovery/1 -TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxNextTabRecovery/1
-TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxShiftSearch/0 -TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxShiftSearch/0
...@@ -37,6 +32,10 @@ ...@@ -37,6 +32,10 @@
-TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/0 -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/0
-TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/1 -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/1
# crbug.com/913549
-StickyKeysBrowserTest.OpenTrayMenu
-StickyKeysBrowserTest.SearchLeftOmnibox
# This test is flaky. https://crbug.com/897879 # This test is flaky. https://crbug.com/897879
-ExtensionApiTest.DisplayModeWindowIsInFullscreen -ExtensionApiTest.DisplayModeWindowIsInFullscreen
......
...@@ -18,11 +18,11 @@ class EventDispatcher; ...@@ -18,11 +18,11 @@ class EventDispatcher;
class EventTarget; class EventTarget;
struct EventDispatchDetails { struct EventDispatchDetails {
EventDispatchDetails() bool dispatcher_destroyed = false;
: dispatcher_destroyed(false), bool target_destroyed = false;
target_destroyed(false) {}
bool dispatcher_destroyed; // Set to true if an EventRewriter discards the event.
bool target_destroyed; bool event_discarded = false;
}; };
class EVENTS_EXPORT EventDispatcherDelegate { class EVENTS_EXPORT EventDispatcherDelegate {
......
...@@ -71,7 +71,9 @@ EventDispatchDetails EventSource::SendEventToSinkFromRewriter( ...@@ -71,7 +71,9 @@ EventDispatchDetails EventSource::SendEventToSinkFromRewriter(
status = (*it)->RewriteEvent(*event_for_rewriting, &rewritten_event); status = (*it)->RewriteEvent(*event_for_rewriting, &rewritten_event);
if (status == EVENT_REWRITE_DISCARD) { if (status == EVENT_REWRITE_DISCARD) {
CHECK(!rewritten_event); CHECK(!rewritten_event);
return EventDispatchDetails(); EventDispatchDetails details;
details.event_discarded = true;
return details;
} }
if (status == EVENT_REWRITE_CONTINUE) { if (status == EVENT_REWRITE_CONTINUE) {
CHECK(!rewritten_event); CHECK(!rewritten_event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment