1 // Copyright 2014 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.
5 #include "ui/events/event_rewriter.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/events/test/test_event_processor.h"
19 // To test the handling of |EventRewriter|s through |EventSource|,
20 // we rewrite and test event types.
21 class TestEvent
: public Event
{
23 explicit TestEvent(EventType type
)
24 : Event(type
, base::TimeDelta(), 0), unique_id_(next_unique_id_
++) {}
25 ~TestEvent() override
{}
26 int unique_id() const { return unique_id_
; }
29 static int next_unique_id_
;
33 int TestEvent::next_unique_id_
= 0;
35 // TestEventRewriteProcessor is set up with a sequence of event types,
36 // and fails if the events received via OnEventFromSource() do not match
37 // this sequence. These expected event types are consumed on receipt.
38 class TestEventRewriteProcessor
: public test::TestEventProcessor
{
40 TestEventRewriteProcessor() {}
41 ~TestEventRewriteProcessor() override
{ CheckAllReceived(); }
43 void AddExpectedEvent(EventType type
) { expected_events_
.push_back(type
); }
44 // Test that all expected events have been received.
45 void CheckAllReceived() { EXPECT_TRUE(expected_events_
.empty()); }
48 EventDispatchDetails
OnEventFromSource(Event
* event
) override
{
49 EXPECT_FALSE(expected_events_
.empty());
50 EXPECT_EQ(expected_events_
.front(), event
->type());
51 expected_events_
.pop_front();
52 return EventDispatchDetails();
56 std::list
<EventType
> expected_events_
;
57 DISALLOW_COPY_AND_ASSIGN(TestEventRewriteProcessor
);
60 // Trivial EventSource that does nothing but send events.
61 class TestEventRewriteSource
: public EventSource
{
63 explicit TestEventRewriteSource(EventProcessor
* processor
)
64 : processor_(processor
) {}
65 EventProcessor
* GetEventProcessor() override
{ return processor_
; }
66 void Send(EventType type
) {
67 scoped_ptr
<Event
> event(new TestEvent(type
));
68 (void)SendEventToProcessor(event
.get());
72 EventProcessor
* processor_
;
75 // This EventRewriter always returns the same status, and if rewriting, the
76 // same event type; it is used to test simple rewriting, and rewriter addition,
77 // removal, and sequencing. Consequently EVENT_REWRITE_DISPATCH_ANOTHER is not
78 // supported here (calls to NextDispatchEvent() would continue indefinitely).
79 class TestConstantEventRewriter
: public EventRewriter
{
81 TestConstantEventRewriter(EventRewriteStatus status
, EventType type
)
82 : status_(status
), type_(type
) {
83 CHECK_NE(EVENT_REWRITE_DISPATCH_ANOTHER
, status
);
86 EventRewriteStatus
RewriteEvent(const Event
& event
,
87 scoped_ptr
<Event
>* rewritten_event
) override
{
88 if (status_
== EVENT_REWRITE_REWRITTEN
)
89 rewritten_event
->reset(new TestEvent(type_
));
92 EventRewriteStatus
NextDispatchEvent(const Event
& last_event
,
93 scoped_ptr
<Event
>* new_event
) override
{
99 EventRewriteStatus status_
;
103 // This EventRewriter runs a simple state machine; it is used to test
104 // EVENT_REWRITE_DISPATCH_ANOTHER.
105 class TestStateMachineEventRewriter
: public EventRewriter
{
107 TestStateMachineEventRewriter() : last_rewritten_event_(0), state_(0) {}
108 void AddRule(int from_state
, EventType from_type
,
109 int to_state
, EventType to_type
, EventRewriteStatus to_status
) {
110 RewriteResult r
= {to_state
, to_type
, to_status
};
111 rules_
.insert(std::pair
<RewriteCase
, RewriteResult
>(
112 RewriteCase(from_state
, from_type
), r
));
114 EventRewriteStatus
RewriteEvent(const Event
& event
,
115 scoped_ptr
<Event
>* rewritten_event
) override
{
116 RewriteRules::iterator find
=
117 rules_
.find(RewriteCase(state_
, event
.type()));
118 if (find
== rules_
.end())
119 return EVENT_REWRITE_CONTINUE
;
120 if ((find
->second
.status
== EVENT_REWRITE_REWRITTEN
) ||
121 (find
->second
.status
== EVENT_REWRITE_DISPATCH_ANOTHER
)) {
122 last_rewritten_event_
= new TestEvent(find
->second
.type
);
123 rewritten_event
->reset(last_rewritten_event_
);
125 last_rewritten_event_
= 0;
127 state_
= find
->second
.state
;
128 return find
->second
.status
;
130 EventRewriteStatus
NextDispatchEvent(const Event
& last_event
,
131 scoped_ptr
<Event
>* new_event
) override
{
132 EXPECT_TRUE(last_rewritten_event_
);
133 const TestEvent
* arg_last
= static_cast<const TestEvent
*>(&last_event
);
134 EXPECT_EQ(last_rewritten_event_
->unique_id(), arg_last
->unique_id());
135 const TestEvent
* arg_new
= static_cast<const TestEvent
*>(new_event
->get());
136 EXPECT_FALSE(arg_new
&& arg_last
->unique_id() == arg_new
->unique_id());
137 return RewriteEvent(last_event
, new_event
);
141 typedef std::pair
<int, EventType
> RewriteCase
;
142 struct RewriteResult
{
145 EventRewriteStatus status
;
147 typedef std::map
<RewriteCase
, RewriteResult
> RewriteRules
;
149 TestEvent
* last_rewritten_event_
;
155 TEST(EventRewriterTest
, EventRewriting
) {
156 // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE;
157 // it is placed at the beginning of the chain and later removed,
158 // to verify that rewriter removal works.
159 TestConstantEventRewriter
r0(EVENT_REWRITE_REWRITTEN
, ET_CANCEL_MODE
);
161 // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE;
162 // it is placed at the beginning of the chain to verify that a
163 // later rewriter sees the events.
164 TestConstantEventRewriter
r1(EVENT_REWRITE_CONTINUE
, ET_UNKNOWN
);
166 // TestEventRewriter r2 has a state machine, primarily to test
167 // |EVENT_REWRITE_DISPATCH_ANOTHER|.
168 TestStateMachineEventRewriter r2
;
170 // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE;
171 // it is placed at the end of the chain to verify that previously
172 // rewritten events are not passed further down the chain.
173 TestConstantEventRewriter
r3(EVENT_REWRITE_REWRITTEN
, ET_CANCEL_MODE
);
175 TestEventRewriteProcessor p
;
176 TestEventRewriteSource
s(&p
);
177 s
.AddEventRewriter(&r0
);
178 s
.AddEventRewriter(&r1
);
179 s
.AddEventRewriter(&r2
);
181 // These events should be rewritten by r0 to ET_CANCEL_MODE.
182 p
.AddExpectedEvent(ET_CANCEL_MODE
);
183 s
.Send(ET_MOUSE_DRAGGED
);
184 p
.AddExpectedEvent(ET_CANCEL_MODE
);
185 s
.Send(ET_MOUSE_PRESSED
);
186 p
.CheckAllReceived();
188 // Remove r0, and verify that it's gone and that events make it through.
189 s
.AddEventRewriter(&r3
);
190 s
.RemoveEventRewriter(&r0
);
191 r2
.AddRule(0, ET_SCROLL_FLING_START
,
192 0, ET_SCROLL_FLING_CANCEL
, EVENT_REWRITE_REWRITTEN
);
193 p
.AddExpectedEvent(ET_SCROLL_FLING_CANCEL
);
194 s
.Send(ET_SCROLL_FLING_START
);
195 p
.CheckAllReceived();
196 s
.RemoveEventRewriter(&r3
);
198 // Verify EVENT_REWRITE_DISPATCH_ANOTHER using a state machine
199 // (that happens to be analogous to sticky keys).
200 r2
.AddRule(0, ET_KEY_PRESSED
,
201 1, ET_KEY_PRESSED
, EVENT_REWRITE_CONTINUE
);
202 r2
.AddRule(1, ET_MOUSE_PRESSED
,
203 0, ET_MOUSE_PRESSED
, EVENT_REWRITE_CONTINUE
);
204 r2
.AddRule(1, ET_KEY_RELEASED
,
205 2, ET_KEY_RELEASED
, EVENT_REWRITE_DISCARD
);
206 r2
.AddRule(2, ET_MOUSE_RELEASED
,
207 3, ET_MOUSE_RELEASED
, EVENT_REWRITE_DISPATCH_ANOTHER
);
208 r2
.AddRule(3, ET_MOUSE_RELEASED
,
209 0, ET_KEY_RELEASED
, EVENT_REWRITE_REWRITTEN
);
210 p
.AddExpectedEvent(ET_KEY_PRESSED
);
211 s
.Send(ET_KEY_PRESSED
);
212 s
.Send(ET_KEY_RELEASED
);
213 p
.AddExpectedEvent(ET_MOUSE_PRESSED
);
214 s
.Send(ET_MOUSE_PRESSED
);
216 // Removing rewriters r1 and r3 shouldn't affect r2.
217 s
.RemoveEventRewriter(&r1
);
218 s
.RemoveEventRewriter(&r3
);
220 // Continue with the state-based rewriting.
221 p
.AddExpectedEvent(ET_MOUSE_RELEASED
);
222 p
.AddExpectedEvent(ET_KEY_RELEASED
);
223 s
.Send(ET_MOUSE_RELEASED
);
224 p
.CheckAllReceived();