1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32
33 #include <gdk/gdk.h>
34 #include <gtest/gtest.h>
35
36 #include "WebInputEvent.h"
37 #include "WebInputEventFactory.h"
38
39 using WebKit::WebMouseEvent;
40 using WebKit::WebInputEventFactory;
41
42 namespace {
43
TEST(WebInputEventFactoryTest,DoubleClick)44 TEST(WebInputEventFactoryTest, DoubleClick)
45 {
46 GdkEventButton firstClick;
47 firstClick.type = GDK_BUTTON_PRESS;
48 firstClick.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
49 firstClick.x = firstClick.y = firstClick.x_root = firstClick.y_root = 100;
50 firstClick.state = 0;
51 firstClick.time = 0;
52 firstClick.button = 1;
53
54 // Single click works.
55 WebMouseEvent firstClickEvent = WebInputEventFactory::mouseEvent(&firstClick);
56 EXPECT_EQ(1, firstClickEvent.clickCount);
57
58 // Make sure double click works.
59 GdkEventButton secondClick = firstClick;
60 secondClick.time = firstClick.time + 100;
61 WebMouseEvent secondClickEvent = WebInputEventFactory::mouseEvent(&secondClick);
62 EXPECT_EQ(2, secondClickEvent.clickCount);
63
64 // Reset the click count.
65 firstClick.time += 10000;
66 firstClickEvent = WebInputEventFactory::mouseEvent(&firstClick);
67 EXPECT_EQ(1, firstClickEvent.clickCount);
68
69 // Two clicks with a long gap in between aren't counted as a double click.
70 secondClick = firstClick;
71 secondClick.time = firstClick.time + 1000;
72 secondClickEvent = WebInputEventFactory::mouseEvent(&secondClick);
73 EXPECT_EQ(1, secondClickEvent.clickCount);
74
75 // Reset the click count.
76 firstClick.time += 10000;
77 firstClickEvent = WebInputEventFactory::mouseEvent(&firstClick);
78 EXPECT_EQ(1, firstClickEvent.clickCount);
79
80 // Two clicks far apart (horizontally) aren't counted as a double click.
81 secondClick = firstClick;
82 secondClick.time = firstClick.time + 1;
83 secondClick.x = firstClick.x + 100;
84 secondClickEvent = WebInputEventFactory::mouseEvent(&secondClick);
85 EXPECT_EQ(1, secondClickEvent.clickCount);
86
87 // Reset the click count.
88 firstClick.time += 10000;
89 firstClickEvent = WebInputEventFactory::mouseEvent(&firstClick);
90 EXPECT_EQ(1, firstClickEvent.clickCount);
91
92 // Two clicks far apart (vertically) aren't counted as a double click.
93 secondClick = firstClick;
94 secondClick.time = firstClick.time + 1;
95 secondClick.x = firstClick.y + 100;
96 secondClickEvent = WebInputEventFactory::mouseEvent(&secondClick);
97 EXPECT_EQ(1, secondClickEvent.clickCount);
98
99 // Reset the click count.
100 firstClick.time += 10000;
101 firstClickEvent = WebInputEventFactory::mouseEvent(&firstClick);
102 EXPECT_EQ(1, firstClickEvent.clickCount);
103
104 // Two clicks on different windows aren't a double click.
105 secondClick = firstClick;
106 secondClick.time = firstClick.time + 1;
107 secondClick.window = static_cast<GdkWindow*>(GINT_TO_POINTER(2));
108 secondClickEvent = WebInputEventFactory::mouseEvent(&secondClick);
109 EXPECT_EQ(1, secondClickEvent.clickCount);
110 }
111
TEST(WebInputEventFactoryTest,MouseUpClickCount)112 TEST(WebInputEventFactoryTest, MouseUpClickCount)
113 {
114 GdkEventButton mouseDown;
115 memset(&mouseDown, 0, sizeof(mouseDown));
116 mouseDown.type = GDK_BUTTON_PRESS;
117 mouseDown.window = static_cast<GdkWindow*>(GINT_TO_POINTER(1));
118 mouseDown.x = mouseDown.y = mouseDown.x_root = mouseDown.y_root = 100;
119 mouseDown.time = 0;
120 mouseDown.button = 1;
121
122 // Properly set the last click time, so that the internal state won't be affected by previous tests.
123 WebInputEventFactory::mouseEvent(&mouseDown);
124
125 mouseDown.time += 10000;
126 GdkEventButton mouseUp = mouseDown;
127 mouseUp.type = GDK_BUTTON_RELEASE;
128 WebMouseEvent mouseDownEvent;
129 WebMouseEvent mouseUpEvent;
130
131 // Click for three times.
132 for (int i = 1; i < 4; ++i) {
133 mouseDown.time += 100;
134 mouseDownEvent = WebInputEventFactory::mouseEvent(&mouseDown);
135 EXPECT_EQ(i, mouseDownEvent.clickCount);
136
137 mouseUp.time = mouseDown.time + 50;
138 mouseUpEvent = WebInputEventFactory::mouseEvent(&mouseUp);
139 EXPECT_EQ(i, mouseUpEvent.clickCount);
140 }
141
142 // Reset the click count.
143 mouseDown.time += 10000;
144 mouseDownEvent = WebInputEventFactory::mouseEvent(&mouseDown);
145 EXPECT_EQ(1, mouseDownEvent.clickCount);
146
147 // Moving the cursor for a significant distance will reset the click count to 0.
148 GdkEventMotion mouseMove;
149 memset(&mouseMove, 0, sizeof(mouseMove));
150 mouseMove.type = GDK_MOTION_NOTIFY;
151 mouseMove.window = mouseDown.window;
152 mouseMove.time = mouseDown.time;
153 mouseMove.x = mouseMove.y = mouseMove.x_root = mouseMove.y_root = mouseDown.x + 100;
154 WebInputEventFactory::mouseEvent(&mouseMove);
155
156 mouseUp.time = mouseDown.time + 50;
157 mouseUpEvent = WebInputEventFactory::mouseEvent(&mouseUp);
158 EXPECT_EQ(0, mouseUpEvent.clickCount);
159
160 // Reset the click count.
161 mouseDown.time += 10000;
162 mouseDownEvent = WebInputEventFactory::mouseEvent(&mouseDown);
163 EXPECT_EQ(1, mouseDownEvent.clickCount);
164
165 // Moving the cursor with a significant delay will reset the click count to 0.
166 mouseMove.time = mouseDown.time + 1000;
167 mouseMove.x = mouseMove.y = mouseMove.x_root = mouseMove.y_root = mouseDown.x;
168 WebInputEventFactory::mouseEvent(&mouseMove);
169
170 mouseUp.time = mouseMove.time + 50;
171 mouseUpEvent = WebInputEventFactory::mouseEvent(&mouseUp);
172 EXPECT_EQ(0, mouseUpEvent.clickCount);
173 }
174
175 } // anonymous namespace
176