summaryrefslogtreecommitdiffstats
path: root/ui/base/events
diff options
context:
space:
mode:
Diffstat (limited to 'ui/base/events')
-rw-r--r--ui/base/events/event_dispatcher.h3
-rw-r--r--ui/base/events/event_dispatcher_unittest.cc52
2 files changed, 53 insertions, 2 deletions
diff --git a/ui/base/events/event_dispatcher.h b/ui/base/events/event_dispatcher.h
index ff58e3b..33cb043 100644
--- a/ui/base/events/event_dispatcher.h
+++ b/ui/base/events/event_dispatcher.h
@@ -91,6 +91,9 @@ class UI_EXPORT EventDispatcher {
// dispatching the event to the event handler.
template<class T>
int DispatchEvent(EventHandler* handler, T* event) {
+ // If the target has been invalidated or deleted, don't dispatch the event.
+ if (!CanDispatchToTarget(event->target()))
+ return ui::ER_CONSUMED;
bool destroyed = false;
set_on_destroy_ = &destroyed;
int result = DispatchEventToSingleHandler(handler, event);
diff --git a/ui/base/events/event_dispatcher_unittest.cc b/ui/base/events/event_dispatcher_unittest.cc
index 36cbd43..89285e4 100644
--- a/ui/base/events/event_dispatcher_unittest.cc
+++ b/ui/base/events/event_dispatcher_unittest.cc
@@ -12,11 +12,14 @@ namespace {
class TestTarget : public EventTarget {
public:
- TestTarget() : parent_(NULL) {}
+ TestTarget() : parent_(NULL), valid_(true) {}
virtual ~TestTarget() {}
void set_parent(TestTarget* parent) { parent_ = parent; }
+ bool valid() const { return valid_; }
+ void set_valid(bool valid) { valid_ = valid; }
+
void AddHandlerId(int id) {
handler_list_.push_back(id);
}
@@ -39,6 +42,7 @@ class TestTarget : public EventTarget {
TestTarget* parent_;
std::vector<int> handler_list_;
+ bool valid_;
DISALLOW_COPY_AND_ASSIGN(TestTarget);
};
@@ -132,6 +136,22 @@ class EventHandlerDestroyDispatcher : public TestEventHandler {
DISALLOW_COPY_AND_ASSIGN(EventHandlerDestroyDispatcher);
};
+// Invalidates the target when it receives any event.
+class InvalidateTargetEventHandler : public TestEventHandler {
+ public:
+ InvalidateTargetEventHandler(int id) : TestEventHandler(id) {}
+ virtual ~InvalidateTargetEventHandler() {}
+
+ private:
+ virtual void ReceivedEvent(Event* event) {
+ TestEventHandler::ReceivedEvent(event);
+ TestTarget* target = static_cast<TestTarget*>(event->target());
+ target->set_valid(false);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(InvalidateTargetEventHandler);
+};
+
class TestEventDispatcher : public EventDispatcher {
public:
TestEventDispatcher() {}
@@ -140,7 +160,8 @@ class TestEventDispatcher : public EventDispatcher {
private:
// Overridden from EventDispatcher:
virtual bool CanDispatchToTarget(EventTarget* target) OVERRIDE {
- return true;
+ TestTarget* test_target = static_cast<TestTarget*>(target);
+ return test_target->valid();
}
DISALLOW_COPY_AND_ASSIGN(TestEventDispatcher);
@@ -317,4 +338,31 @@ TEST(EventDispatcherTest, EventDispatcherDestroyTarget) {
}
}
+// Tests that a target becoming invalid in the middle of pre- or post-target
+// event processing aborts processing.
+TEST(EventDispatcherTest, EventDispatcherInvalidateTarget) {
+ TestEventDispatcher dispatcher;
+ TestTarget target;
+ TestEventHandler h1(1);
+ InvalidateTargetEventHandler invalidate_handler(2);
+ TestEventHandler h3(3);
+
+ target.AddPreTargetHandler(&h1);
+ target.AddPreTargetHandler(&invalidate_handler);
+ target.AddPreTargetHandler(&h3);
+
+ h1.set_expect_pre_target(true);
+ invalidate_handler.set_expect_pre_target(true);
+ // |h3| should not receive events as the target will be invalidated.
+ h3.set_expect_pre_target(false);
+
+ MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4), gfx::Point(3, 4), 0);
+ int result = dispatcher.ProcessEvent(&target, &mouse);
+ EXPECT_FALSE(target.valid());
+ EXPECT_EQ(ER_CONSUMED, result);
+ EXPECT_EQ(2U, target.handler_list().size());
+ EXPECT_EQ(1, target.handler_list()[0]);
+ EXPECT_EQ(2, target.handler_list()[1]);
+}
+
} // namespace ui