1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/events/event_source.h"
6
7 #include "ui/events/event_rewriter_continuation.h"
8 #include "ui/events/event_sink.h"
9
10 namespace ui {
11
12 namespace {
13
IsLocatedEventWithDifferentLocations(const Event & event)14 bool IsLocatedEventWithDifferentLocations(const Event& event) {
15 if (!event.IsLocatedEvent())
16 return false;
17 const LocatedEvent* located_event = event.AsLocatedEvent();
18 return located_event->target() &&
19 located_event->location_f() != located_event->root_location_f();
20 }
21
22 } // namespace
23
24 class EventSource::EventRewriterContinuationImpl
25 : public EventRewriterContinuation {
26 public:
27 // Constructs an EventRewriterContinuationImpl at the end of the source's
28 // rewriter list.
Create(EventSource * const source,EventRewriter * rewriter)29 static void Create(EventSource* const source, EventRewriter* rewriter) {
30 DCHECK(source);
31 DCHECK(rewriter);
32 DCHECK(source->FindContinuation(rewriter) == source->rewriter_list_.end());
33 source->rewriter_list_.push_back(
34 std::make_unique<EventRewriterContinuationImpl>(source, rewriter));
35 EventRewriterList::iterator it = source->rewriter_list_.end();
36 --it;
37 CHECK((*it)->rewriter() == rewriter);
38 (*it)->self_ = it;
39 }
40
EventRewriterContinuationImpl(EventSource * const source,EventRewriter * rewriter)41 EventRewriterContinuationImpl(EventSource* const source,
42 EventRewriter* rewriter)
43 : source_(source),
44 rewriter_(rewriter),
45 self_(source->rewriter_list_.end()) {}
~EventRewriterContinuationImpl()46 ~EventRewriterContinuationImpl() override {}
47
rewriter() const48 EventRewriter* rewriter() const { return rewriter_; }
49
GetWeakPtr()50 base::WeakPtr<EventRewriterContinuationImpl> GetWeakPtr() {
51 return weak_ptr_factory_.GetWeakPtr();
52 }
53
54 // EventRewriterContinuation overrides:
SendEvent(const Event * event)55 EventDispatchDetails SendEvent(const Event* event) override {
56 EventRewriterList::iterator next = self_;
57 ++next;
58 if (next == source_->rewriter_list_.end())
59 return SendEventFinally(event);
60 return (*next)->rewriter_->RewriteEvent(*event, (*next)->GetWeakPtr());
61 }
62
SendEventFinally(const Event * event)63 EventDispatchDetails SendEventFinally(const Event* event) override {
64 return source_->DeliverEventToSink(const_cast<Event*>(event));
65 }
66
DiscardEvent()67 EventDispatchDetails DiscardEvent() override {
68 ui::EventDispatchDetails details;
69 details.event_discarded = true;
70 return details;
71 }
72
73 private:
74 EventSource* const source_;
75 EventRewriter* rewriter_;
76 EventRewriterList::iterator self_;
77
78 base::WeakPtrFactory<EventRewriterContinuationImpl> weak_ptr_factory_{this};
79 DISALLOW_COPY_AND_ASSIGN(EventRewriterContinuationImpl);
80 };
81
EventSource()82 EventSource::EventSource() {}
83
~EventSource()84 EventSource::~EventSource() {}
85
AddEventRewriter(EventRewriter * rewriter)86 void EventSource::AddEventRewriter(EventRewriter* rewriter) {
87 EventRewriterContinuationImpl::Create(this, rewriter);
88 }
89
RemoveEventRewriter(EventRewriter * rewriter)90 void EventSource::RemoveEventRewriter(EventRewriter* rewriter) {
91 EventRewriterList::iterator it = FindContinuation(rewriter);
92 if (it == rewriter_list_.end()) {
93 // We need to tolerate attempting to remove an unregistered
94 // EventRewriter, because many unit tests currently do so:
95 // the rewriter gets added to the current root window source
96 // on construction, and removed from the current root window
97 // source on destruction, but the root window changes in
98 // between.
99 LOG(WARNING) << "EventRewriter not registered";
100 return;
101 }
102 rewriter_list_.erase(it);
103 }
104
SendEventToSink(const Event * event)105 EventDispatchDetails EventSource::SendEventToSink(const Event* event) {
106 return SendEventToSinkFromRewriter(event, nullptr);
107 }
108
DeliverEventToSink(Event * event)109 EventDispatchDetails EventSource::DeliverEventToSink(Event* event) {
110 EventSink* sink = GetEventSink();
111 CHECK(sink);
112 return sink->OnEventFromSource(event);
113 }
114
SendEventToSinkFromRewriter(const Event * event,const EventRewriter * rewriter)115 EventDispatchDetails EventSource::SendEventToSinkFromRewriter(
116 const Event* event,
117 const EventRewriter* rewriter) {
118 std::unique_ptr<ui::Event> event_for_rewriting_ptr;
119 const Event* event_for_rewriting = event;
120 if (!rewriter_list_.empty() && IsLocatedEventWithDifferentLocations(*event)) {
121 // EventRewriters don't expect an event with differing location and
122 // root-location (because they don't honor the target). Provide such an
123 // event.
124 event_for_rewriting_ptr = ui::Event::Clone(*event);
125 event_for_rewriting_ptr->AsLocatedEvent()->set_location_f(
126 event_for_rewriting_ptr->AsLocatedEvent()->root_location_f());
127 event_for_rewriting = event_for_rewriting_ptr.get();
128 }
129 EventRewriterList::iterator it = rewriter_list_.begin();
130 if (rewriter) {
131 // If a rewriter reposted |event|, only send it to subsequent rewriters.
132 it = FindContinuation(rewriter);
133 CHECK(it != rewriter_list_.end());
134 ++it;
135 }
136 if (it == rewriter_list_.end())
137 return DeliverEventToSink(const_cast<Event*>(event));
138 return (*it)->rewriter()->RewriteEvent(*event_for_rewriting,
139 (*it)->GetWeakPtr());
140 }
141
FindContinuation(const EventRewriter * rewriter)142 EventSource::EventRewriterList::iterator EventSource::FindContinuation(
143 const EventRewriter* rewriter) {
144 auto it = find_if(
145 rewriter_list_.begin(), rewriter_list_.end(),
146 [rewriter](const std::unique_ptr<EventRewriterContinuationImpl>& p)
147 -> bool { return p->rewriter() == rewriter; });
148 return it;
149 }
150
151 } // namespace ui
152