Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(650)

Side by Side Diff: chrome/browser/chromeos/events/event_rewriter.cc

Issue 653423004: Suppress Xorg generated key repeat events for Hotrod remote (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: test fixes Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/events/event_rewriter.h" 5 #include "chrome/browser/chromeos/events/event_rewriter.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "ash/sticky_keys/sticky_keys_controller.h" 9 #include "ash/sticky_keys/sticky_keys_controller.h"
10 #include "ash/wm/window_state.h" 10 #include "ash/wm/window_state.h"
(...skipping 12 matching lines...) Expand all
23 #include "chromeos/ime/ime_keyboard.h" 23 #include "chromeos/ime/ime_keyboard.h"
24 #include "chromeos/ime/input_method_manager.h" 24 #include "chromeos/ime/input_method_manager.h"
25 #include "components/user_manager/user_manager.h" 25 #include "components/user_manager/user_manager.h"
26 #include "ui/events/event.h" 26 #include "ui/events/event.h"
27 #include "ui/events/event_utils.h" 27 #include "ui/events/event_utils.h"
28 #include "ui/events/keycodes/keyboard_code_conversion.h" 28 #include "ui/events/keycodes/keyboard_code_conversion.h"
29 #include "ui/wm/core/window_util.h" 29 #include "ui/wm/core/window_util.h"
30 30
31 #if defined(USE_X11) 31 #if defined(USE_X11)
32 #include <X11/extensions/XInput2.h> 32 #include <X11/extensions/XInput2.h>
33 #include <X11/Xatom.h>
33 #include <X11/Xlib.h> 34 #include <X11/Xlib.h>
35
36 #ifndef XI_PROP_PRODUCT_ID
37 #define XI_PROP_PRODUCT_ID "Device Product ID"
38 #endif
39
34 // Get rid of macros from Xlib.h that conflicts with other parts of the code. 40 // Get rid of macros from Xlib.h that conflicts with other parts of the code.
35 #undef RootWindow 41 #undef RootWindow
36 #undef Status 42 #undef Status
37 43
38 #include "ui/base/x/x11_util.h" 44 #include "ui/base/x/x11_util.h"
39 #include "ui/events/keycodes/keyboard_code_conversion_x.h" 45 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
40 #endif 46 #endif
41 47
42 namespace chromeos { 48 namespace chromeos {
43 49
44 namespace { 50 namespace {
45 51
52 // Hotrod controller vendor/product ids.
53 const int kHotrodRemoteVendorId = 0x0471;
54 const int kHotrodRemoteProductId = 0x21cc;
55 const int kUnknownVendorId = -1;
56 const int kUnknownProductId = -1;
57
46 // Table of key properties of remappable keys and/or remapping targets. 58 // Table of key properties of remappable keys and/or remapping targets.
47 // This is searched in two distinct ways: 59 // This is searched in two distinct ways:
48 // - |remap_to| is an |input_method::ModifierKey|, which is the form 60 // - |remap_to| is an |input_method::ModifierKey|, which is the form
49 // held in user preferences. |GetRemappedKey()| maps this to the 61 // held in user preferences. |GetRemappedKey()| maps this to the
50 // corresponding |key_code| and characterstic event |flag|. 62 // corresponding |key_code| and characterstic event |flag|.
51 // - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this 63 // - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this
52 // to the corresponding user preference |pref_name| for that flag's 64 // to the corresponding user preference |pref_name| for that flag's
53 // key, so that it can then be remapped as above. 65 // key, so that it can then be remapped as above.
54 // In addition |kModifierRemappingCtrl| is a direct reference to the 66 // In addition |kModifierRemappingCtrl| is a direct reference to the
55 // Control key entry in the table, used in handling Chromebook Diamond 67 // Control key entry in the table, used in handling Chromebook Diamond
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 if (!profile || !extensions::ExtensionCommandsGlobalRegistry::Get(profile)) 132 if (!profile || !extensions::ExtensionCommandsGlobalRegistry::Get(profile))
121 return false; 133 return false;
122 134
123 int modifiers = flags & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | 135 int modifiers = flags & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
124 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN); 136 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
125 ui::Accelerator accelerator(key_code, modifiers); 137 ui::Accelerator accelerator(key_code, modifiers);
126 return extensions::ExtensionCommandsGlobalRegistry::Get(profile) 138 return extensions::ExtensionCommandsGlobalRegistry::Get(profile)
127 ->IsRegistered(accelerator); 139 ->IsRegistered(accelerator);
128 } 140 }
129 141
130 EventRewriter::DeviceType GetDeviceType(const std::string& device_name) { 142 EventRewriter::DeviceType GetDeviceType(const std::string& device_name,
143 int vendor_id,
144 int product_id) {
145 if (vendor_id == kHotrodRemoteVendorId &&
146 product_id == kHotrodRemoteProductId) {
147 return EventRewriter::kDeviceHotrodRemote;
148 }
149
150 if (LowerCaseEqualsASCII(device_name, "virtual core keyboard"))
151 return EventRewriter::kDeviceVirtualCoreKeyboard;
152
131 std::vector<std::string> tokens; 153 std::vector<std::string> tokens;
132 Tokenize(device_name, " .", &tokens); 154 Tokenize(device_name, " .", &tokens);
133 155
156
134 // If the |device_name| contains the two words, "apple" and "keyboard", treat 157 // If the |device_name| contains the two words, "apple" and "keyboard", treat
135 // it as an Apple keyboard. 158 // it as an Apple keyboard.
136 bool found_apple = false; 159 bool found_apple = false;
137 bool found_keyboard = false; 160 bool found_keyboard = false;
138 for (size_t i = 0; i < tokens.size(); ++i) { 161 for (size_t i = 0; i < tokens.size(); ++i) {
139 if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple")) 162 if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple"))
140 found_apple = true; 163 found_apple = true;
141 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard")) 164 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
142 found_keyboard = true; 165 found_keyboard = true;
143 if (found_apple && found_keyboard) 166 if (found_apple && found_keyboard)
(...skipping 14 matching lines...) Expand all
158 } 181 }
159 182
160 EventRewriter::~EventRewriter() { 183 EventRewriter::~EventRewriter() {
161 } 184 }
162 185
163 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedForTesting( 186 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedForTesting(
164 int device_id, 187 int device_id,
165 const std::string& device_name) { 188 const std::string& device_name) {
166 // Tests must avoid XI2 reserved device IDs. 189 // Tests must avoid XI2 reserved device IDs.
167 DCHECK((device_id < 0) || (device_id > 1)); 190 DCHECK((device_id < 0) || (device_id > 1));
168 return KeyboardDeviceAddedInternal(device_id, device_name); 191 return KeyboardDeviceAddedInternal(device_id,
192 device_name,
193 kUnknownVendorId,
194 kUnknownProductId);
169 } 195 }
170 196
171 void EventRewriter::RewriteMouseButtonEventForTesting( 197 void EventRewriter::RewriteMouseButtonEventForTesting(
172 const ui::MouseEvent& event, 198 const ui::MouseEvent& event,
173 scoped_ptr<ui::Event>* rewritten_event) { 199 scoped_ptr<ui::Event>* rewritten_event) {
174 RewriteMouseButtonEvent(event, rewritten_event); 200 RewriteMouseButtonEvent(event, rewritten_event);
175 } 201 }
176 202
177 ui::EventRewriteStatus EventRewriter::RewriteEvent( 203 ui::EventRewriteStatus EventRewriter::RewriteEvent(
178 const ui::Event& event, 204 const ui::Event& event,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 rewritten_key_event->set_flags(flags); 299 rewritten_key_event->set_flags(flags);
274 rewritten_key_event->set_key_code(key_code); 300 rewritten_key_event->set_key_code(key_code);
275 #if defined(USE_X11) 301 #if defined(USE_X11)
276 ui::UpdateX11EventForFlags(rewritten_key_event); 302 ui::UpdateX11EventForFlags(rewritten_key_event);
277 rewritten_key_event->NormalizeFlags(); 303 rewritten_key_event->NormalizeFlags();
278 #endif 304 #endif
279 rewritten_event->reset(rewritten_key_event); 305 rewritten_event->reset(rewritten_key_event);
280 } 306 }
281 307
282 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) { 308 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) {
283 if (!device_id_to_type_.count(device_id)) 309 std::map<int, DeviceType>::const_iterator iter =
284 KeyboardDeviceAdded(device_id); 310 device_id_to_type_.find(device_id);
311 DeviceType type;
312 if (iter != device_id_to_type_.end())
313 type = iter->second;
314 else
315 type = KeyboardDeviceAdded(device_id);
316
317 // Ignore virtual Xorg keyboard (magic that generates key repeat
318 // events). Pretend that the previous real keyboard is the one that is still
319 // in use.
320 if (type == kDeviceVirtualCoreKeyboard)
321 return;
322
285 last_keyboard_device_id_ = device_id; 323 last_keyboard_device_id_ = device_id;
286 } 324 }
287 325
288 const PrefService* EventRewriter::GetPrefService() const { 326 const PrefService* EventRewriter::GetPrefService() const {
289 if (pref_service_for_testing_) 327 if (pref_service_for_testing_)
290 return pref_service_for_testing_; 328 return pref_service_for_testing_;
291 Profile* profile = ProfileManager::GetActiveUserProfile(); 329 Profile* profile = ProfileManager::GetActiveUserProfile();
292 return profile ? profile->GetPrefs() : NULL; 330 return profile ? profile->GetPrefs() : NULL;
293 } 331 }
294 332
295 bool EventRewriter::IsAppleKeyboard() const { 333 bool EventRewriter::IsAppleKeyboard() const {
334 return IsLastKeyboardOfType(kDeviceAppleKeyboard);
335 }
336
337 bool EventRewriter::IsHotrodRemote() const {
338 return IsLastKeyboardOfType(kDeviceHotrodRemote);
339 }
340
341 bool EventRewriter::IsLastKeyboardOfType(DeviceType device_type) const {
296 if (last_keyboard_device_id_ == ui::ED_UNKNOWN_DEVICE) 342 if (last_keyboard_device_id_ == ui::ED_UNKNOWN_DEVICE)
297 return false; 343 return false;
298 344
299 // Check which device generated |event|. 345 // Check which device generated |event|.
300 std::map<int, DeviceType>::const_iterator iter = 346 std::map<int, DeviceType>::const_iterator iter =
301 device_id_to_type_.find(last_keyboard_device_id_); 347 device_id_to_type_.find(last_keyboard_device_id_);
302 if (iter == device_id_to_type_.end()) { 348 if (iter == device_id_to_type_.end()) {
303 LOG(ERROR) << "Device ID " << last_keyboard_device_id_ << " is unknown."; 349 LOG(ERROR) << "Device ID " << last_keyboard_device_id_ << " is unknown.";
304 return false; 350 return false;
305 } 351 }
306 352
307 const DeviceType type = iter->second; 353 const DeviceType type = iter->second;
308 return type == kDeviceAppleKeyboard; 354 return type == device_type;
309 } 355 }
310 356
311 bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const { 357 bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const {
312 const PrefService* prefs = GetPrefService(); 358 const PrefService* prefs = GetPrefService();
313 if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) && 359 if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) &&
314 prefs->GetBoolean(prefs::kLanguageSendFunctionKeys)) 360 prefs->GetBoolean(prefs::kLanguageSendFunctionKeys))
315 return true; 361 return true;
316 362
317 ash::wm::WindowState* state = ash::wm::GetActiveWindowState(); 363 ash::wm::WindowState* state = ash::wm::GetActiveWindowState();
318 return state ? state->top_row_keys_are_function_keys() : false; 364 return state ? state->top_row_keys_are_function_keys() : false;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 return false; 426 return false;
381 } 427 }
382 428
383 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( 429 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent(
384 const ui::KeyEvent& key_event, 430 const ui::KeyEvent& key_event,
385 scoped_ptr<ui::Event>* rewritten_event) { 431 scoped_ptr<ui::Event>* rewritten_event) {
386 if (IsExtensionCommandRegistered(key_event.key_code(), key_event.flags())) 432 if (IsExtensionCommandRegistered(key_event.key_code(), key_event.flags()))
387 return ui::EVENT_REWRITE_CONTINUE; 433 return ui::EVENT_REWRITE_CONTINUE;
388 if (key_event.source_device_id() != ui::ED_UNKNOWN_DEVICE) 434 if (key_event.source_device_id() != ui::ED_UNKNOWN_DEVICE)
389 DeviceKeyPressedOrReleased(key_event.source_device_id()); 435 DeviceKeyPressedOrReleased(key_event.source_device_id());
436
437 // Drop repeated keys from Hotrod remote.
438 if ((key_event.flags() & ui::EF_IS_REPEAT) &&
439 (key_event.type() == ui::ET_KEY_PRESSED) &&
440 IsHotrodRemote() && key_event.key_code() != ui::VKEY_BACK) {
441 return ui::EVENT_REWRITE_DISCARD;
442 }
443
390 MutableKeyState state = {key_event.flags(), key_event.key_code()}; 444 MutableKeyState state = {key_event.flags(), key_event.key_code()};
391 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See 445 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
392 // crbug.com/136465. 446 // crbug.com/136465.
393 if (!(key_event.flags() & ui::EF_FINAL)) { 447 if (!(key_event.flags() & ui::EF_FINAL)) {
394 RewriteModifierKeys(key_event, &state); 448 RewriteModifierKeys(key_event, &state);
395 RewriteNumPadKeys(key_event, &state); 449 RewriteNumPadKeys(key_event, &state);
396 } 450 }
451
397 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; 452 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
398 bool is_sticky_key_extension_command = false; 453 bool is_sticky_key_extension_command = false;
399 if (sticky_keys_controller_) { 454 if (sticky_keys_controller_) {
400 status = sticky_keys_controller_->RewriteKeyEvent( 455 status = sticky_keys_controller_->RewriteKeyEvent(
401 key_event, state.key_code, &state.flags); 456 key_event, state.key_code, &state.flags);
402 if (status == ui::EVENT_REWRITE_DISCARD) 457 if (status == ui::EVENT_REWRITE_DISCARD)
403 return ui::EVENT_REWRITE_DISCARD; 458 return ui::EVENT_REWRITE_DISCARD;
404 is_sticky_key_extension_command = 459 is_sticky_key_extension_command =
405 IsExtensionCommandRegistered(state.key_code, state.flags); 460 IsExtensionCommandRegistered(state.key_code, state.flags);
406 } 461 }
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 pressed_device_ids_.insert(mouse_event.source_device_id()); 902 pressed_device_ids_.insert(mouse_event.source_device_id());
848 else 903 else
849 pressed_device_ids_.erase(mouse_event.source_device_id()); 904 pressed_device_ids_.erase(mouse_event.source_device_id());
850 return ui::EF_RIGHT_MOUSE_BUTTON; 905 return ui::EF_RIGHT_MOUSE_BUTTON;
851 } 906 }
852 return ui::EF_NONE; 907 return ui::EF_NONE;
853 } 908 }
854 909
855 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedInternal( 910 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedInternal(
856 int device_id, 911 int device_id,
857 const std::string& device_name) { 912 const std::string& device_name,
858 const DeviceType type = GetDeviceType(device_name); 913 int vendor_id,
914 int product_id) {
915 const DeviceType type = GetDeviceType(device_name, vendor_id, product_id);
859 if (type == kDeviceAppleKeyboard) { 916 if (type == kDeviceAppleKeyboard) {
860 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 917 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
861 << "id=" << device_id; 918 << "id=" << device_id;
919 } else if (type == kDeviceHotrodRemote) {
920 VLOG(1) << "Hotrod remote '" << device_name << "' connected: "
921 << "id=" << device_id;
922 } else if (type == kDeviceVirtualCoreKeyboard) {
923 VLOG(1) << "Xorg virtual '" << device_name << "' connected: "
924 << "id=" << device_id;
925 } else {
926 VLOG(1) << "Unknown keyboard '" << device_name << "' connected: "
927 << "id=" << device_id;
862 } 928 }
863 // Always overwrite the existing device_id since the X server may reuse a 929 // Always overwrite the existing device_id since the X server may reuse a
864 // device id for an unattached device. 930 // device id for an unattached device.
865 device_id_to_type_[device_id] = type; 931 device_id_to_type_[device_id] = type;
866 return type; 932 return type;
867 } 933 }
868 934
869 void EventRewriter::KeyboardDeviceAdded(int device_id) { 935 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAdded(int device_id) {
870 #if defined(USE_X11) 936 #if defined(USE_X11)
871 DCHECK_NE(XIAllDevices, device_id); 937 DCHECK_NE(XIAllDevices, device_id);
872 DCHECK_NE(XIAllMasterDevices, device_id); 938 DCHECK_NE(XIAllMasterDevices, device_id);
873 if (device_id == XIAllDevices || device_id == XIAllMasterDevices) { 939 if (device_id == XIAllDevices || device_id == XIAllMasterDevices) {
874 LOG(ERROR) << "Unexpected device_id passed: " << device_id; 940 LOG(ERROR) << "Unexpected device_id passed: " << device_id;
875 return; 941 return kDeviceUnknown;
876 } 942 }
877 943
944 Atom product_id_atom =
945 XInternAtom(gfx::GetXDisplay(), XI_PROP_PRODUCT_ID, 1);
946
878 int ndevices_return = 0; 947 int ndevices_return = 0;
879 XIDeviceInfo* device_info = 948 XIDeviceInfo* device_info =
880 XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return); 949 XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return);
881 950
882 // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices, 951 // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices,
883 // the number of devices found should be either 0 (not found) or 1. 952 // the number of devices found should be either 0 (not found) or 1.
884 if (!device_info) { 953 if (!device_info) {
885 LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown."; 954 LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown.";
886 return; 955 return kDeviceUnknown;
887 } 956 }
888 957
958 DeviceType dev_type;
889 DCHECK_EQ(1, ndevices_return); 959 DCHECK_EQ(1, ndevices_return);
890 for (int i = 0; i < ndevices_return; ++i) { 960 for (int i = 0; i < ndevices_return; ++i) {
961 // Get keyboard product and vendor id.
962 int vendor_id = kUnknownVendorId;
963 int product_id = kUnknownProductId;
964 uint32* product_info = NULL;
965 Atom type;
966 int format_return;
967 unsigned long num_items_return;
968 unsigned long bytes_after_return;
969 if (XIGetProperty(gfx::GetXDisplay(),
970 device_info[i].deviceid,
971 product_id_atom,
972 0,
973 2,
974 0,
975 XA_INTEGER,
976 &type,
977 &format_return,
978 &num_items_return,
979 &bytes_after_return,
980 reinterpret_cast<unsigned char **>(&product_info)) == 0 &&
981 product_info) {
982 vendor_id = product_info[0];
983 product_id = product_info[1];
984 }
985
891 DCHECK_EQ(device_id, device_info[i].deviceid); // see the comment above. 986 DCHECK_EQ(device_id, device_info[i].deviceid); // see the comment above.
892 DCHECK(device_info[i].name); 987 DCHECK(device_info[i].name);
893 KeyboardDeviceAddedInternal(device_info[i].deviceid, device_info[i].name); 988 dev_type = KeyboardDeviceAddedInternal(device_info[i].deviceid,
989 device_info[i].name,
990 vendor_id,
991 product_id);
894 } 992 }
895
896 XIFreeDeviceInfo(device_info); 993 XIFreeDeviceInfo(device_info);
994 return dev_type;
897 #else 995 #else
898 KeyboardDeviceAddedInternal(device_id, "keyboard"); 996 // TODO(spang): Figure out where we can get keyboard vendor/product id from in
997 // Ozone/Freon version.
998 return KeyboardDeviceAddedInternal(device_id,
999 "keyboard",
1000 kUnknownVendorId,
1001 kUnknownProductId);
899 #endif 1002 #endif
900 } 1003 }
901 1004
902 } // namespace chromeos 1005 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/events/event_rewriter.h ('k') | chrome/browser/chromeos/events/event_rewriter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698