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