1 // Copyright (c) 2012 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 "base/memory/scoped_ptr.h" 6 #include "testing/gtest/include/gtest/gtest.h" 7 #include "ui/events/event.h" 8 #include "ui/events/event_utils.h" 9 #include "ui/events/keycodes/dom4/keycode_converter.h" 10 #include "ui/events/test/events_test_utils.h" 11 12 #if defined(USE_X11) 13 #include <X11/Xlib.h> 14 #include "ui/events/test/events_test_utils_x11.h" 15 #include "ui/gfx/x/x11_types.h" 16 #endif 17 18 namespace ui { 19 20 TEST(EventTest, NoNativeEvent) { 21 KeyEvent keyev(ET_KEY_PRESSED, VKEY_SPACE, 0, false); 22 EXPECT_FALSE(keyev.HasNativeEvent()); 23 } 24 25 TEST(EventTest, NativeEvent) { 26 #if defined(OS_WIN) 27 MSG native_event = { NULL, WM_KEYUP, VKEY_A, 0 }; 28 KeyEvent keyev(native_event, false); 29 EXPECT_TRUE(keyev.HasNativeEvent()); 30 #elif defined(USE_X11) 31 ScopedXI2Event event; 32 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_A, 0); 33 KeyEvent keyev(event, false); 34 EXPECT_TRUE(keyev.HasNativeEvent()); 35 #endif 36 } 37 38 TEST(EventTest, GetCharacter) { 39 // Check if Control+Enter returns 10. 40 KeyEvent keyev1(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN, false); 41 EXPECT_EQ(10, keyev1.GetCharacter()); 42 // Check if Enter returns 13. 43 KeyEvent keyev2(ET_KEY_PRESSED, VKEY_RETURN, 0, false); 44 EXPECT_EQ(13, keyev2.GetCharacter()); 45 46 #if defined(USE_X11) 47 // For X11, test the functions with native_event() as well. crbug.com/107837 48 ScopedXI2Event event; 49 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN); 50 KeyEvent keyev3(event, false); 51 EXPECT_EQ(10, keyev3.GetCharacter()); 52 53 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_RETURN, 0); 54 KeyEvent keyev4(event, false); 55 EXPECT_EQ(13, keyev4.GetCharacter()); 56 #endif 57 } 58 59 TEST(EventTest, ClickCount) { 60 const gfx::Point origin(0, 0); 61 MouseEvent mouseev(ET_MOUSE_PRESSED, origin, origin, 0); 62 for (int i = 1; i <=3 ; ++i) { 63 mouseev.SetClickCount(i); 64 EXPECT_EQ(i, mouseev.GetClickCount()); 65 } 66 } 67 68 TEST(EventTest, Repeated) { 69 const gfx::Point origin(0, 0); 70 MouseEvent mouse_ev1(ET_MOUSE_PRESSED, origin, origin, 0); 71 MouseEvent mouse_ev2(ET_MOUSE_PRESSED, origin, origin, 0); 72 LocatedEventTestApi test_ev1(&mouse_ev1); 73 LocatedEventTestApi test_ev2(&mouse_ev2); 74 75 base::TimeDelta start = base::TimeDelta::FromMilliseconds(0); 76 base::TimeDelta soon = start + base::TimeDelta::FromMilliseconds(1); 77 base::TimeDelta later = start + base::TimeDelta::FromMilliseconds(1000); 78 79 // Close point. 80 test_ev1.set_location(gfx::Point(0, 0)); 81 test_ev2.set_location(gfx::Point(1, 0)); 82 test_ev1.set_time_stamp(start); 83 test_ev2.set_time_stamp(soon); 84 EXPECT_TRUE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2)); 85 86 // Too far. 87 test_ev1.set_location(gfx::Point(0, 0)); 88 test_ev2.set_location(gfx::Point(10, 0)); 89 test_ev1.set_time_stamp(start); 90 test_ev2.set_time_stamp(soon); 91 EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2)); 92 93 // Too long a time between clicks. 94 test_ev1.set_location(gfx::Point(0, 0)); 95 test_ev2.set_location(gfx::Point(0, 0)); 96 test_ev1.set_time_stamp(start); 97 test_ev2.set_time_stamp(later); 98 EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2)); 99 } 100 101 TEST(EventTest, KeyEvent) { 102 static const struct { 103 KeyboardCode key_code; 104 int flags; 105 uint16 character; 106 } kTestData[] = { 107 { VKEY_A, 0, 'a' }, 108 { VKEY_A, EF_SHIFT_DOWN, 'A' }, 109 { VKEY_A, EF_CAPS_LOCK_DOWN, 'A' }, 110 { VKEY_A, EF_SHIFT_DOWN | EF_CAPS_LOCK_DOWN, 'a' }, 111 { VKEY_A, EF_CONTROL_DOWN, 0x01 }, 112 { VKEY_A, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x01' }, 113 { VKEY_Z, 0, 'z' }, 114 { VKEY_Z, EF_SHIFT_DOWN, 'Z' }, 115 { VKEY_Z, EF_CAPS_LOCK_DOWN, 'Z' }, 116 { VKEY_Z, EF_SHIFT_DOWN | EF_CAPS_LOCK_DOWN, 'z' }, 117 { VKEY_Z, EF_CONTROL_DOWN, '\x1A' }, 118 { VKEY_Z, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1A' }, 119 120 { VKEY_2, EF_CONTROL_DOWN, '\0' }, 121 { VKEY_2, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' }, 122 { VKEY_6, EF_CONTROL_DOWN, '\0' }, 123 { VKEY_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1E' }, 124 { VKEY_OEM_MINUS, EF_CONTROL_DOWN, '\0' }, 125 { VKEY_OEM_MINUS, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1F' }, 126 { VKEY_OEM_4, EF_CONTROL_DOWN, '\x1B' }, 127 { VKEY_OEM_4, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' }, 128 { VKEY_OEM_5, EF_CONTROL_DOWN, '\x1C' }, 129 { VKEY_OEM_5, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' }, 130 { VKEY_OEM_6, EF_CONTROL_DOWN, '\x1D' }, 131 { VKEY_OEM_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' }, 132 { VKEY_RETURN, EF_CONTROL_DOWN, '\x0A' }, 133 134 { VKEY_0, 0, '0' }, 135 { VKEY_0, EF_SHIFT_DOWN, ')' }, 136 { VKEY_0, EF_SHIFT_DOWN | EF_CAPS_LOCK_DOWN, ')' }, 137 { VKEY_0, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' }, 138 139 { VKEY_9, 0, '9' }, 140 { VKEY_9, EF_SHIFT_DOWN, '(' }, 141 { VKEY_9, EF_SHIFT_DOWN | EF_CAPS_LOCK_DOWN, '(' }, 142 { VKEY_9, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' }, 143 144 { VKEY_NUMPAD0, EF_CONTROL_DOWN, '\0' }, 145 { VKEY_NUMPAD0, EF_SHIFT_DOWN, '0' }, 146 147 { VKEY_NUMPAD9, EF_CONTROL_DOWN, '\0' }, 148 { VKEY_NUMPAD9, EF_SHIFT_DOWN, '9' }, 149 150 { VKEY_TAB, EF_CONTROL_DOWN, '\0' }, 151 { VKEY_TAB, EF_SHIFT_DOWN, '\t' }, 152 153 { VKEY_MULTIPLY, EF_CONTROL_DOWN, '\0' }, 154 { VKEY_MULTIPLY, EF_SHIFT_DOWN, '*' }, 155 { VKEY_ADD, EF_CONTROL_DOWN, '\0' }, 156 { VKEY_ADD, EF_SHIFT_DOWN, '+' }, 157 { VKEY_SUBTRACT, EF_CONTROL_DOWN, '\0' }, 158 { VKEY_SUBTRACT, EF_SHIFT_DOWN, '-' }, 159 { VKEY_DECIMAL, EF_CONTROL_DOWN, '\0' }, 160 { VKEY_DECIMAL, EF_SHIFT_DOWN, '.' }, 161 { VKEY_DIVIDE, EF_CONTROL_DOWN, '\0' }, 162 { VKEY_DIVIDE, EF_SHIFT_DOWN, '/' }, 163 164 { VKEY_OEM_1, EF_CONTROL_DOWN, '\0' }, 165 { VKEY_OEM_1, EF_SHIFT_DOWN, ':' }, 166 { VKEY_OEM_PLUS, EF_CONTROL_DOWN, '\0' }, 167 { VKEY_OEM_PLUS, EF_SHIFT_DOWN, '+' }, 168 { VKEY_OEM_COMMA, EF_CONTROL_DOWN, '\0' }, 169 { VKEY_OEM_COMMA, EF_SHIFT_DOWN, '<' }, 170 { VKEY_OEM_PERIOD, EF_CONTROL_DOWN, '\0' }, 171 { VKEY_OEM_PERIOD, EF_SHIFT_DOWN, '>' }, 172 { VKEY_OEM_3, EF_CONTROL_DOWN, '\0' }, 173 { VKEY_OEM_3, EF_SHIFT_DOWN, '~' }, 174 }; 175 176 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) { 177 KeyEvent key(ET_KEY_PRESSED, 178 kTestData[i].key_code, 179 kTestData[i].flags, 180 false); 181 EXPECT_EQ(kTestData[i].character, key.GetCharacter()) 182 << " Index:" << i << " key_code:" << kTestData[i].key_code; 183 } 184 } 185 186 TEST(EventTest, KeyEventDirectUnicode) { 187 KeyEvent key(ET_KEY_PRESSED, VKEY_UNKNOWN, EF_SHIFT_DOWN, false); 188 key.set_character(0x1234U); 189 EXPECT_EQ(0x1234U, key.GetCharacter()); 190 KeyEvent key2(ET_KEY_RELEASED, VKEY_UNKNOWN, EF_CONTROL_DOWN, false); 191 key2.set_character(0x4321U); 192 EXPECT_EQ(0x4321U, key2.GetCharacter()); 193 } 194 195 TEST(EventTest, NormalizeKeyEventFlags) { 196 #if defined(USE_X11) 197 // Normalize flags when KeyEvent is created from XEvent. 198 ScopedXI2Event event; 199 { 200 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN); 201 KeyEvent keyev(event, false); 202 EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags()); 203 } 204 { 205 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN); 206 KeyEvent keyev(event, false); 207 EXPECT_EQ(EF_NONE, keyev.flags()); 208 } 209 { 210 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN); 211 KeyEvent keyev(event, false); 212 EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags()); 213 } 214 { 215 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN); 216 KeyEvent keyev(event, false); 217 EXPECT_EQ(EF_NONE, keyev.flags()); 218 } 219 { 220 event.InitKeyEvent(ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN); 221 KeyEvent keyev(event, false); 222 EXPECT_EQ(EF_ALT_DOWN, keyev.flags()); 223 } 224 { 225 event.InitKeyEvent(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN); 226 KeyEvent keyev(event, false); 227 EXPECT_EQ(EF_NONE, keyev.flags()); 228 } 229 #endif 230 231 // Do not normalize flags for synthesized events without 232 // KeyEvent::NormalizeFlags called explicitly. 233 { 234 KeyEvent keyev(ET_KEY_PRESSED, VKEY_SHIFT, EF_SHIFT_DOWN, false); 235 EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags()); 236 } 237 { 238 KeyEvent keyev(ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN, false); 239 EXPECT_EQ(EF_SHIFT_DOWN, keyev.flags()); 240 keyev.NormalizeFlags(); 241 EXPECT_EQ(EF_NONE, keyev.flags()); 242 } 243 { 244 KeyEvent keyev(ET_KEY_PRESSED, VKEY_CONTROL, EF_CONTROL_DOWN, false); 245 EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags()); 246 } 247 { 248 KeyEvent keyev(ET_KEY_RELEASED, VKEY_CONTROL, EF_CONTROL_DOWN, false); 249 EXPECT_EQ(EF_CONTROL_DOWN, keyev.flags()); 250 keyev.NormalizeFlags(); 251 EXPECT_EQ(EF_NONE, keyev.flags()); 252 } 253 { 254 KeyEvent keyev(ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN, false); 255 EXPECT_EQ(EF_ALT_DOWN, keyev.flags()); 256 } 257 { 258 KeyEvent keyev(ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN, false); 259 EXPECT_EQ(EF_ALT_DOWN, keyev.flags()); 260 keyev.NormalizeFlags(); 261 EXPECT_EQ(EF_NONE, keyev.flags()); 262 } 263 } 264 265 TEST(EventTest, KeyEventCopy) { 266 KeyEvent key(ET_KEY_PRESSED, VKEY_A, EF_NONE, false); 267 scoped_ptr<KeyEvent> copied_key(new KeyEvent(key)); 268 EXPECT_EQ(copied_key->type(), key.type()); 269 EXPECT_EQ(copied_key->key_code(), key.key_code()); 270 } 271 272 TEST(EventTest, KeyEventCode) { 273 KeycodeConverter* conv = KeycodeConverter::GetInstance(); 274 275 const char kCodeForSpace[] = "Space"; 276 const uint16 kNativeCodeSpace = conv->CodeToNativeKeycode(kCodeForSpace); 277 ASSERT_NE(conv->InvalidNativeKeycode(), kNativeCodeSpace); 278 279 { 280 KeyEvent key(ET_KEY_PRESSED, VKEY_SPACE, kCodeForSpace, EF_NONE, false); 281 EXPECT_EQ(kCodeForSpace, key.code()); 282 } 283 { 284 // Regardless the KeyEvent.key_code (VKEY_RETURN), code should be 285 // the specified value. 286 KeyEvent key(ET_KEY_PRESSED, VKEY_RETURN, kCodeForSpace, EF_NONE, false); 287 EXPECT_EQ(kCodeForSpace, key.code()); 288 } 289 { 290 // If the synthetic event is initialized without code, it returns 291 // an empty string. 292 // TODO(komatsu): Fill a fallback value assuming the US keyboard layout. 293 KeyEvent key(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE, false); 294 EXPECT_TRUE(key.code().empty()); 295 } 296 #if defined(USE_X11) 297 { 298 // KeyEvent converts from the native keycode (XKB) to the code. 299 ScopedXI2Event xevent; 300 xevent.InitKeyEvent(ET_KEY_PRESSED, VKEY_SPACE, kNativeCodeSpace); 301 KeyEvent key(xevent, false); 302 EXPECT_EQ(kCodeForSpace, key.code()); 303 } 304 #endif // USE_X11 305 #if defined(OS_WIN) 306 { 307 // Test a non extended key. 308 ASSERT_EQ((kNativeCodeSpace & 0xFF), kNativeCodeSpace); 309 310 const LPARAM lParam = GetLParamFromScanCode(kNativeCodeSpace); 311 MSG native_event = { NULL, WM_KEYUP, VKEY_SPACE, lParam }; 312 KeyEvent key(native_event, false); 313 314 // KeyEvent converts from the native keycode (scan code) to the code. 315 EXPECT_EQ(kCodeForSpace, key.code()); 316 } 317 { 318 const char kCodeForHome[] = "Home"; 319 const uint16 kNativeCodeHome = 0xe047; 320 321 // 'Home' is an extended key with 0xe000 bits. 322 ASSERT_NE((kNativeCodeHome & 0xFF), kNativeCodeHome); 323 const LPARAM lParam = GetLParamFromScanCode(kNativeCodeHome); 324 325 MSG native_event = { NULL, WM_KEYUP, VKEY_HOME, lParam }; 326 KeyEvent key(native_event, false); 327 328 // KeyEvent converts from the native keycode (scan code) to the code. 329 EXPECT_EQ(kCodeForHome, key.code()); 330 } 331 #endif // OS_WIN 332 } 333 334 } // namespace ui 335