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

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

Issue 165463002: event-rewrite: Clean up how events are rewritten. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix-debug Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 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/ui/ash/event_rewriter.h" 5 #include "chrome/browser/chromeos/event_rewriter.h"
6
7 #include <X11/extensions/XInput2.h>
8 #include <X11/keysym.h>
9 #include <X11/XF86keysym.h>
10 #include <X11/Xlib.h>
11 // Get rid of macros from Xlib.h that conflicts with other parts of the code.
12 #undef RootWindow
13 #undef Status
6 14
7 #include <vector> 15 #include <vector>
8 16
9 #include "ash/shell.h" 17 #include "ash/shell.h"
18 #include "ash/wm/window_state.h"
19 #include "ash/wm/window_util.h"
20 #include "base/command_line.h"
10 #include "base/logging.h" 21 #include "base/logging.h"
11 #include "base/prefs/pref_service.h" 22 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "ui/aura/root_window.h"
15 #include "ui/events/event.h"
16 #include "ui/events/event_utils.h"
17 #include "ui/events/keycodes/keyboard_code_conversion.h"
18
19 #if defined(OS_CHROMEOS)
20 #include <X11/extensions/XInput2.h>
21 #include <X11/keysym.h>
22 #include <X11/XF86keysym.h>
23 #include <X11/Xlib.h>
24
25 // Get rid of a macro from Xlib.h that conflicts with OwnershipService class.
26 #undef Status
27
28 #include "ash/wm/window_state.h"
29 #include "base/command_line.h"
30 #include "base/sys_info.h" 24 #include "base/sys_info.h"
31 #include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h" 25 #include "chrome/browser/chromeos/keyboard_driven_event_rewriter.h"
32 #include "chrome/browser/chromeos/login/login_display_host_impl.h" 26 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
33 #include "chrome/browser/chromeos/login/user_manager.h" 27 #include "chrome/browser/chromeos/login/user_manager.h"
34 #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h" 28 #include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
29 #include "chrome/browser/profiles/profile_manager.h"
35 #include "chrome/common/pref_names.h" 30 #include "chrome/common/pref_names.h"
36 #include "chromeos/chromeos_switches.h" 31 #include "chromeos/chromeos_switches.h"
37 #include "chromeos/ime/input_method_manager.h" 32 #include "chromeos/ime/input_method_manager.h"
38 #include "chromeos/ime/xkeyboard.h" 33 #include "chromeos/ime/xkeyboard.h"
34 #include "ui/aura/root_window.h"
39 #include "ui/base/x/x11_util.h" 35 #include "ui/base/x/x11_util.h"
36 #include "ui/events/event.h"
37 #include "ui/events/event_utils.h"
40 #include "ui/events/keycodes/keyboard_code_conversion_x.h" 38 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
41 #include "ui/views/corewm/window_util.h" 39 #include "ui/views/corewm/window_util.h"
42 #endif
43 40
44 namespace { 41 namespace {
45 42
46 const int kBadDeviceId = -1; 43 const int kBadDeviceId = -1;
47 44
48 #if defined(OS_CHROMEOS)
49 const char kNeo2LayoutId[] = "xkb:de:neo:ger"; 45 const char kNeo2LayoutId[] = "xkb:de:neo:ger";
50 const char kCaMultixLayoutId[] = "xkb:ca:multix:fra"; 46 const char kCaMultixLayoutId[] = "xkb:ca:multix:fra";
51 47
52 // A key code and a flag we should use when a key is remapped to |remap_to|. 48 // A key code and a flag we should use when a key is remapped to |remap_to|.
53 const struct ModifierRemapping { 49 const struct ModifierRemapping {
54 int remap_to; 50 int remap_to;
55 int flag; 51 int flag;
56 unsigned int native_modifier; 52 unsigned int native_modifier;
57 ui::KeyboardCode keycode; 53 ui::KeyboardCode keycode;
58 KeySym native_keysyms[4]; // left, right, shift+left, shift+right. 54 KeySym native_keysyms[4]; // left, right, shift+left, shift+right.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask, 125 // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask,
130 // it's not possible to make both features work. For now, we don't remap 126 // it's not possible to make both features work. For now, we don't remap
131 // Mod3Mask when Neo2 is in use. 127 // Mod3Mask when Neo2 is in use.
132 // TODO(yusukes): Remove the restriction. 128 // TODO(yusukes): Remove the restriction.
133 chromeos::input_method::InputMethodManager* manager = 129 chromeos::input_method::InputMethodManager* manager =
134 chromeos::input_method::InputMethodManager::Get(); 130 chromeos::input_method::InputMethodManager::Get();
135 return manager->GetCurrentInputMethod().id() == kNeo2LayoutId || 131 return manager->GetCurrentInputMethod().id() == kNeo2LayoutId ||
136 manager->GetCurrentInputMethod().id() == kCaMultixLayoutId; 132 manager->GetCurrentInputMethod().id() == kCaMultixLayoutId;
137 } 133 }
138 134
139 #endif // defined(OS_CHROMEOS) 135 } // namespace
140 136
141 } // namespace 137 namespace chromeos {
142 138
143 EventRewriter::EventRewriter() 139 EventRewriter::EventRewriter()
144 : last_device_id_(kBadDeviceId), 140 : last_device_id_(kBadDeviceId),
145 #if defined(OS_CHROMEOS)
146 xkeyboard_for_testing_(NULL), 141 xkeyboard_for_testing_(NULL),
147 keyboard_driven_event_rewriter_( 142 keyboard_driven_event_rewriter_(new KeyboardDrivenEventRewriter),
148 new chromeos::KeyboardDrivenEventRewriter),
149 #endif
150 pref_service_for_testing_(NULL) { 143 pref_service_for_testing_(NULL) {
151 // The ash shell isn't instantiated for our unit tests. 144 // The ash shell isn't instantiated for our unit tests.
152 if (ash::Shell::HasInstance()) { 145 if (ash::Shell::HasInstance()) {
153 ash::Shell::GetPrimaryRootWindow()->GetDispatcher()-> 146 ash::Shell::GetPrimaryRootWindow()->GetDispatcher()->
154 AddRootWindowObserver(this); 147 AddRootWindowObserver(this);
155 } 148 }
156 #if defined(OS_CHROMEOS) 149 base::MessageLoopForUI::current()->AddObserver(this);
157 if (base::SysInfo::IsRunningOnChromeOS()) { 150 if (base::SysInfo::IsRunningOnChromeOS()) {
158 chromeos::XInputHierarchyChangedEventListener::GetInstance() 151 XInputHierarchyChangedEventListener::GetInstance()->AddObserver(this);
159 ->AddObserver(this);
160 } 152 }
161 RefreshKeycodes(); 153 RefreshKeycodes();
162 #endif
163 } 154 }
164 155
165 EventRewriter::~EventRewriter() { 156 EventRewriter::~EventRewriter() {
157 base::MessageLoopForUI::current()->RemoveObserver(this);
166 if (ash::Shell::HasInstance()) { 158 if (ash::Shell::HasInstance()) {
167 ash::Shell::GetPrimaryRootWindow()->GetDispatcher()-> 159 ash::Shell::GetPrimaryRootWindow()->GetDispatcher()->
168 RemoveRootWindowObserver(this); 160 RemoveRootWindowObserver(this);
169 } 161 }
170 #if defined(OS_CHROMEOS)
171 if (base::SysInfo::IsRunningOnChromeOS()) { 162 if (base::SysInfo::IsRunningOnChromeOS()) {
172 chromeos::XInputHierarchyChangedEventListener::GetInstance() 163 XInputHierarchyChangedEventListener::GetInstance()->RemoveObserver(this);
173 ->RemoveObserver(this);
174 } 164 }
175 #endif
176 } 165 }
177 166
178 EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting( 167 EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting(
179 int device_id, 168 int device_id,
180 const std::string& device_name) { 169 const std::string& device_name) {
181 return DeviceAddedInternal(device_id, device_name); 170 return DeviceAddedInternal(device_id, device_name);
182 } 171 }
183 172
184 // static 173 // static
185 EventRewriter::DeviceType EventRewriter::GetDeviceType( 174 EventRewriter::DeviceType EventRewriter::GetDeviceType(
(...skipping 10 matching lines...) Expand all
196 found_apple = true; 185 found_apple = true;
197 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard")) 186 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
198 found_keyboard = true; 187 found_keyboard = true;
199 if (found_apple && found_keyboard) 188 if (found_apple && found_keyboard)
200 return kDeviceAppleKeyboard; 189 return kDeviceAppleKeyboard;
201 } 190 }
202 191
203 return kDeviceUnknown; 192 return kDeviceUnknown;
204 } 193 }
205 194
206 void EventRewriter::RewriteForTesting(ui::KeyEvent* event) { 195 void EventRewriter::RewriteForTesting(XEvent* event) {
207 Rewrite(event); 196 Rewrite(event);
208 } 197 }
209 198
210 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterKeyEvent( 199 void EventRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) {
211 ui::KeyEvent* event) { 200 RefreshKeycodes();
212 if (event->HasNativeEvent())
213 Rewrite(event);
214 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT;
215 } 201 }
216 202
217 ash::EventRewriterDelegate::Action EventRewriter::RewriteOrFilterLocatedEvent( 203 base::EventStatus EventRewriter::WillProcessEvent(
218 ui::LocatedEvent* event) { 204 const base::NativeEvent& event) {
219 if (event->HasNativeEvent()) 205 XEvent* xevent = event;
220 RewriteLocatedEvent(event); 206 if (xevent->type == KeyPress || xevent->type == KeyRelease)
221 return ash::EventRewriterDelegate::ACTION_REWRITE_EVENT; 207 Rewrite(xevent);
208 else if (xevent->type == GenericEvent)
209 RewriteLocatedEvent(xevent);
210 return base::EVENT_CONTINUE;
222 } 211 }
223 212
224 void EventRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { 213 void EventRewriter::DidProcessEvent(const base::NativeEvent& event) {
225 #if defined(OS_CHROMEOS)
226 RefreshKeycodes();
227 #endif
228 } 214 }
229 215
230 #if defined(OS_CHROMEOS)
231 void EventRewriter::DeviceAdded(int device_id) { 216 void EventRewriter::DeviceAdded(int device_id) {
232 DCHECK_NE(XIAllDevices, device_id); 217 DCHECK_NE(XIAllDevices, device_id);
233 DCHECK_NE(XIAllMasterDevices, device_id); 218 DCHECK_NE(XIAllMasterDevices, device_id);
234 if (device_id == XIAllDevices || device_id == XIAllMasterDevices) { 219 if (device_id == XIAllDevices || device_id == XIAllMasterDevices) {
235 LOG(ERROR) << "Unexpected device_id passed: " << device_id; 220 LOG(ERROR) << "Unexpected device_id passed: " << device_id;
236 return; 221 return;
237 } 222 }
238 223
239 int ndevices_return = 0; 224 int ndevices_return = 0;
240 XIDeviceInfo* device_info = XIQueryDevice(gfx::GetXDisplay(), 225 XIDeviceInfo* device_info = XIQueryDevice(gfx::GetXDisplay(),
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) { 266 KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) {
282 if (keysym_to_keycode_map_.count(keysym)) 267 if (keysym_to_keycode_map_.count(keysym))
283 return keysym_to_keycode_map_[keysym]; 268 return keysym_to_keycode_map_[keysym];
284 269
285 XDisplay* display = gfx::GetXDisplay(); 270 XDisplay* display = gfx::GetXDisplay();
286 KeyCode keycode = XKeysymToKeycode(display, keysym); 271 KeyCode keycode = XKeysymToKeycode(display, keysym);
287 keysym_to_keycode_map_[keysym] = keycode; 272 keysym_to_keycode_map_[keysym] = keycode;
288 return keycode; 273 return keycode;
289 } 274 }
290 275
291 bool EventRewriter::TopRowKeysAreFunctionKeys(ui::KeyEvent* event) const { 276 bool EventRewriter::TopRowKeysAreFunctionKeys(XEvent* event) const {
292 const PrefService* prefs = GetPrefService(); 277 const PrefService* prefs = GetPrefService();
293 if (prefs && 278 if (prefs &&
294 prefs->FindPreference(prefs::kLanguageSendFunctionKeys) && 279 prefs->FindPreference(prefs::kLanguageSendFunctionKeys) &&
295 prefs->GetBoolean(prefs::kLanguageSendFunctionKeys)) 280 prefs->GetBoolean(prefs::kLanguageSendFunctionKeys))
296 return true; 281 return true;
297 282
298 aura::Window* target = static_cast<aura::Window*>(event->target()); 283 ash::wm::WindowState* state = ash::wm::GetActiveWindowState();
299 if (!target) 284 return state ? state->top_row_keys_are_function_keys() : false;
300 return false;
301 aura::Window* top_level = views::corewm::GetToplevelWindow(target);
302 return top_level &&
303 ash::wm::GetWindowState(top_level)->top_row_keys_are_function_keys();
304 } 285 }
305 286
306 bool EventRewriter::RewriteWithKeyboardRemappingsByKeySym( 287 bool EventRewriter::RewriteWithKeyboardRemappingsByKeySym(
307 const KeyboardRemapping* remappings, 288 const KeyboardRemapping* remappings,
308 size_t num_remappings, 289 size_t num_remappings,
309 KeySym keysym, 290 KeySym keysym,
310 unsigned int native_mods, 291 unsigned int native_mods,
311 unsigned int mods,
312 KeySym* remapped_native_keysym, 292 KeySym* remapped_native_keysym,
313 unsigned int* remapped_native_mods, 293 unsigned int* remapped_native_mods) {
314 ui::KeyboardCode* remapped_keycode,
315 unsigned int* remapped_mods) {
316 for (size_t i = 0; i < num_remappings; ++i) { 294 for (size_t i = 0; i < num_remappings; ++i) {
317 const KeyboardRemapping& map = remappings[i]; 295 const KeyboardRemapping& map = remappings[i];
318 296
319 if (keysym != map.input_keysym) 297 if (keysym != map.input_keysym)
320 continue; 298 continue;
321 unsigned int matched_mods = native_mods & map.input_native_mods; 299 unsigned int matched_mods = native_mods & map.input_native_mods;
322 if (matched_mods != map.input_native_mods) 300 if (matched_mods != map.input_native_mods)
323 continue; 301 continue;
324 302
325 *remapped_native_keysym = map.output_keysym; 303 *remapped_native_keysym = map.output_keysym;
326 *remapped_keycode = map.output_keycode;
327 *remapped_native_mods = (native_mods & ~map.input_native_mods) | 304 *remapped_native_mods = (native_mods & ~map.input_native_mods) |
328 map.output_native_mods; 305 map.output_native_mods;
329 *remapped_mods = (mods & ~map.input_mods) | map.output_mods;
330 return true; 306 return true;
331 } 307 }
332 308
333 return false; 309 return false;
334 } 310 }
335 311
336 bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode( 312 bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode(
337 const KeyboardRemapping* remappings, 313 const KeyboardRemapping* remappings,
338 size_t num_remappings, 314 size_t num_remappings,
339 KeyCode keycode, 315 KeyCode keycode,
340 unsigned int native_mods, 316 unsigned int native_mods,
341 unsigned int mods,
342 KeySym* remapped_native_keysym, 317 KeySym* remapped_native_keysym,
343 unsigned int* remapped_native_mods, 318 unsigned int* remapped_native_mods) {
344 ui::KeyboardCode* remapped_keycode,
345 unsigned int* remapped_mods) {
346 for (size_t i = 0; i < num_remappings; ++i) { 319 for (size_t i = 0; i < num_remappings; ++i) {
347 const KeyboardRemapping& map = remappings[i]; 320 const KeyboardRemapping& map = remappings[i];
348 321
349 KeyCode input_keycode = NativeKeySymToNativeKeycode(map.input_keysym); 322 KeyCode input_keycode = NativeKeySymToNativeKeycode(map.input_keysym);
350 if (keycode != input_keycode) 323 if (keycode != input_keycode)
351 continue; 324 continue;
352 unsigned int matched_mods = native_mods & map.input_native_mods; 325 unsigned int matched_mods = native_mods & map.input_native_mods;
353 if (matched_mods != map.input_native_mods) 326 if (matched_mods != map.input_native_mods)
354 continue; 327 continue;
355 328
356 *remapped_native_keysym = map.output_keysym; 329 *remapped_native_keysym = map.output_keysym;
357 *remapped_keycode = map.output_keycode;
358 *remapped_native_mods = (native_mods & ~map.input_native_mods) | 330 *remapped_native_mods = (native_mods & ~map.input_native_mods) |
359 map.output_native_mods; 331 map.output_native_mods;
360 *remapped_mods = (mods & ~map.input_mods) | map.output_mods;
361 return true; 332 return true;
362 } 333 }
363 334
364 return false; 335 return false;
365 } 336 }
366 #endif // defined(OS_CHROMEOS)
367 337
368 const PrefService* EventRewriter::GetPrefService() const { 338 const PrefService* EventRewriter::GetPrefService() const {
369 if (pref_service_for_testing_) 339 if (pref_service_for_testing_)
370 return pref_service_for_testing_; 340 return pref_service_for_testing_;
371 Profile* profile = ProfileManager::GetActiveUserProfile(); 341 Profile* profile = ProfileManager::GetActiveUserProfile();
372 return profile ? profile->GetPrefs() : NULL; 342 return profile ? profile->GetPrefs() : NULL;
373 } 343 }
374 344
375 void EventRewriter::Rewrite(ui::KeyEvent* event) { 345 void EventRewriter::Rewrite(XEvent* event) {
376 #if defined(OS_CHROMEOS)
377 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See 346 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
378 // crbug.com/136465. 347 // crbug.com/136465.
379 if (event->native_event()->xkey.send_event) 348 if (event->xkey.send_event)
380 return; 349 return;
381 350
382 // Keyboard driven rewriting happen first. Skip further processing if event is 351 // Keyboard driven rewriting happen first. Skip further processing if event is
383 // changed. 352 // changed.
384 if (keyboard_driven_event_rewriter_->RewriteIfKeyboardDrivenOnLoginScreen( 353 if (keyboard_driven_event_rewriter_->RewriteIfKeyboardDrivenOnLoginScreen(
385 event)) { 354 event)) {
386 return; 355 return;
387 } 356 }
388 #endif 357
389 RewriteModifiers(event); 358 RewriteModifiers(event);
390 RewriteNumPadKeys(event); 359 RewriteNumPadKeys(event);
391 RewriteExtendedKeys(event); 360 RewriteExtendedKeys(event);
392 RewriteFunctionKeys(event); 361 RewriteFunctionKeys(event);
393 } 362 }
394 363
395 bool EventRewriter::IsAppleKeyboard() const { 364 bool EventRewriter::IsAppleKeyboard() const {
396 if (last_device_id_ == kBadDeviceId) 365 if (last_device_id_ == kBadDeviceId)
397 return false; 366 return false;
398 367
399 // Check which device generated |event|. 368 // Check which device generated |event|.
400 std::map<int, DeviceType>::const_iterator iter = 369 std::map<int, DeviceType>::const_iterator iter =
401 device_id_to_type_.find(last_device_id_); 370 device_id_to_type_.find(last_device_id_);
402 if (iter == device_id_to_type_.end()) { 371 if (iter == device_id_to_type_.end()) {
403 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; 372 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown.";
404 return false; 373 return false;
405 } 374 }
406 375
407 const DeviceType type = iter->second; 376 const DeviceType type = iter->second;
408 return type == kDeviceAppleKeyboard; 377 return type == kDeviceAppleKeyboard;
409 } 378 }
410 379
411 void EventRewriter::GetRemappedModifierMasks( 380 void EventRewriter::GetRemappedModifierMasks(
412 int original_flags,
413 unsigned int original_native_modifiers, 381 unsigned int original_native_modifiers,
414 int* remapped_flags,
415 unsigned int* remapped_native_modifiers) const { 382 unsigned int* remapped_native_modifiers) const {
416 #if defined(OS_CHROMEOS)
417 // TODO(glotov): remove the following condition when we do not restart chrome 383 // TODO(glotov): remove the following condition when we do not restart chrome
418 // when user logs in as guest. See Rewrite() for details. 384 // when user logs in as guest. See Rewrite() for details.
419 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && 385 if (UserManager::Get()->IsLoggedInAsGuest() &&
420 chromeos::LoginDisplayHostImpl::default_host()) { 386 LoginDisplayHostImpl::default_host()) {
421 return; 387 return;
422 } 388 }
423 389
424 const PrefService* pref_service = GetPrefService(); 390 const PrefService* pref_service = GetPrefService();
425 if (!pref_service) 391 if (!pref_service)
426 return; 392 return;
427 393
428 // When a diamond key is not available, a Mod2Mask should not treated as a 394 // When a diamond key is not available, a Mod2Mask should not treated as a
429 // configurable modifier because Mod2Mask may be worked as NumLock mask. 395 // configurable modifier because Mod2Mask may be worked as NumLock mask.
430 // (cf. http://crbug.com/173956) 396 // (cf. http://crbug.com/173956)
(...skipping 10 matching lines...) Expand all
441 if (original_native_modifiers & 407 if (original_native_modifiers &
442 kModifierFlagToPrefName[i].native_modifier) { 408 kModifierFlagToPrefName[i].native_modifier) {
443 const ModifierRemapping* remapped_key = 409 const ModifierRemapping* remapped_key =
444 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service); 410 GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service);
445 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R. 411 // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
446 if (IsAppleKeyboard() && 412 if (IsAppleKeyboard() &&
447 (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) { 413 (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) {
448 remapped_key = kModifierRemappingCtrl; 414 remapped_key = kModifierRemappingCtrl;
449 } 415 }
450 if (remapped_key) { 416 if (remapped_key) {
451 *remapped_flags |= remapped_key->flag;
452 *remapped_native_modifiers |= remapped_key->native_modifier; 417 *remapped_native_modifiers |= remapped_key->native_modifier;
453 } else { 418 } else {
454 *remapped_flags |= kModifierFlagToPrefName[i].flag;
455 *remapped_native_modifiers |= 419 *remapped_native_modifiers |=
456 kModifierFlagToPrefName[i].native_modifier; 420 kModifierFlagToPrefName[i].native_modifier;
457 } 421 }
458 } 422 }
459 } 423 }
460 424
461 *remapped_flags =
462 (original_flags & ~(ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) |
463 *remapped_flags;
464
465 unsigned int native_mask = Mod4Mask | ControlMask | Mod1Mask; 425 unsigned int native_mask = Mod4Mask | ControlMask | Mod1Mask;
466 if (!skip_mod2) 426 if (!skip_mod2)
467 native_mask |= Mod2Mask; 427 native_mask |= Mod2Mask;
468 if (!skip_mod3) 428 if (!skip_mod3)
469 native_mask |= Mod3Mask; 429 native_mask |= Mod3Mask;
470 *remapped_native_modifiers = 430 *remapped_native_modifiers =
471 (original_native_modifiers & ~native_mask) | 431 (original_native_modifiers & ~native_mask) |
472 *remapped_native_modifiers; 432 *remapped_native_modifiers;
473 #endif
474 } 433 }
475 434
476 bool EventRewriter::RewriteModifiers(ui::KeyEvent* event) { 435 bool EventRewriter::RewriteModifiers(XEvent* event) {
477 #if defined(OS_CHROMEOS) 436 DCHECK(event->type == KeyPress || event->type == KeyRelease);
478 // Do nothing if we have just logged in as guest but have not restarted chrome 437 // Do nothing if we have just logged in as guest but have not restarted chrome
479 // process yet (so we are still on the login screen). In this situations we 438 // process yet (so we are still on the login screen). In this situations we
480 // have no user profile so can not do anything useful. 439 // have no user profile so can not do anything useful.
481 // Note that currently, unlike other accounts, when user logs in as guest, we 440 // Note that currently, unlike other accounts, when user logs in as guest, we
482 // restart chrome process. In future this is to be changed. 441 // restart chrome process. In future this is to be changed.
483 // TODO(glotov): remove the following condition when we do not restart chrome 442 // TODO(glotov): remove the following condition when we do not restart chrome
484 // when user logs in as guest. 443 // when user logs in as guest.
485 if (chromeos::UserManager::Get()->IsLoggedInAsGuest() && 444 if (UserManager::Get()->IsLoggedInAsGuest() &&
486 chromeos::LoginDisplayHostImpl::default_host()) 445 LoginDisplayHostImpl::default_host())
487 return false; 446 return false;
488 447
489 const PrefService* pref_service = GetPrefService(); 448 const PrefService* pref_service = GetPrefService();
490 if (!pref_service) 449 if (!pref_service)
491 return false; 450 return false;
492 451
493 DCHECK_EQ(chromeos::input_method::kControlKey, 452 DCHECK_EQ(input_method::kControlKey, kModifierRemappingCtrl->remap_to);
494 kModifierRemappingCtrl->remap_to);
495 453
496 XEvent* xev = event->native_event(); 454 XKeyEvent* xkey = &event->xkey;
497 XKeyEvent* xkey = &(xev->xkey);
498 KeySym keysym = XLookupKeysym(xkey, 0); 455 KeySym keysym = XLookupKeysym(xkey, 0);
499 456 ui::KeyboardCode original_keycode = ui::KeyboardCodeFromNative(event);
500 ui::KeyboardCode remapped_keycode = event->key_code(); 457 ui::KeyboardCode remapped_keycode = original_keycode;
501 KeyCode remapped_native_keycode = xkey->keycode; 458 KeyCode remapped_native_keycode = xkey->keycode;
502 459
503 // First, remap |keysym|. 460 // First, remap |keysym|.
504 const ModifierRemapping* remapped_key = NULL; 461 const ModifierRemapping* remapped_key = NULL;
505 switch (keysym) { 462 switch (keysym) {
506 // On Chrome OS, XF86XK_Launch6 (F15) with Mod2Mask is sent when Diamond 463 // On Chrome OS, XF86XK_Launch6 (F15) with Mod2Mask is sent when Diamond
507 // key is pressed. 464 // key is pressed.
508 case XF86XK_Launch6: 465 case XF86XK_Launch6:
509 // When diamond key is not available, the configuration UI for Diamond 466 // When diamond key is not available, the configuration UI for Diamond
510 // key is not shown. Therefore, ignore the kLanguageRemapDiamondKeyTo 467 // key is not shown. Therefore, ignore the kLanguageRemapDiamondKeyTo
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 case XK_Meta_L: 502 case XK_Meta_L:
546 case XK_Meta_R: 503 case XK_Meta_R:
547 remapped_key = 504 remapped_key =
548 GetRemappedKey(prefs::kLanguageRemapAltKeyTo, *pref_service); 505 GetRemappedKey(prefs::kLanguageRemapAltKeyTo, *pref_service);
549 break; 506 break;
550 default: 507 default:
551 break; 508 break;
552 } 509 }
553 510
554 if (remapped_key) { 511 if (remapped_key) {
512 int flags = ui::EventFlagsFromNative(event);
555 remapped_keycode = remapped_key->keycode; 513 remapped_keycode = remapped_key->keycode;
556 const size_t level = (event->IsShiftDown() ? (1 << 1) : 0) + 514 const size_t level = ((flags & ui::EF_SHIFT_DOWN) ? (1 << 1) : 0) +
557 (IsRight(keysym) ? (1 << 0) : 0); 515 (IsRight(keysym) ? (1 << 0) : 0);
558 const KeySym native_keysym = remapped_key->native_keysyms[level]; 516 const KeySym native_keysym = remapped_key->native_keysyms[level];
559 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym); 517 remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
560 } 518 }
561 519
562 // Next, remap modifier bits. 520 // Next, remap modifier bits.
563 int remapped_flags = 0;
564 unsigned int remapped_native_modifiers = 0U; 521 unsigned int remapped_native_modifiers = 0U;
565 GetRemappedModifierMasks(event->flags(), xkey->state, 522 GetRemappedModifierMasks(xkey->state, &remapped_native_modifiers);
566 &remapped_flags, &remapped_native_modifiers);
567 523
568 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if 524 // Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
569 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external 525 // the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
570 // keyboard is pressed) since X can handle that case. 526 // keyboard is pressed) since X can handle that case.
571 if ((event->type() == ui::ET_KEY_PRESSED) && 527 if (event->type == KeyPress &&
572 (event->key_code() != ui::VKEY_CAPITAL) && 528 original_keycode != ui::VKEY_CAPITAL &&
573 (remapped_keycode == ui::VKEY_CAPITAL)) { 529 remapped_keycode == ui::VKEY_CAPITAL) {
574 chromeos::input_method::XKeyboard* xkeyboard = xkeyboard_for_testing_ ? 530 input_method::XKeyboard* xkeyboard = xkeyboard_for_testing_ ?
575 xkeyboard_for_testing_ : 531 xkeyboard_for_testing_ :
576 chromeos::input_method::InputMethodManager::Get()->GetXKeyboard(); 532 input_method::InputMethodManager::Get()->GetXKeyboard();
577 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled()); 533 xkeyboard->SetCapsLockEnabled(!xkeyboard->CapsLockIsEnabled());
578 } 534 }
579 535
580 OverwriteEvent(event, 536 OverwriteEvent(event, remapped_native_keycode, remapped_native_modifiers);
581 remapped_native_keycode, remapped_native_modifiers,
582 remapped_keycode, remapped_flags);
583 return true; 537 return true;
584 #else
585 // TODO(yusukes): Support Ash on other platforms if needed.
586 return false;
587 #endif
588 } 538 }
589 539
590 bool EventRewriter::RewriteNumPadKeys(ui::KeyEvent* event) { 540 bool EventRewriter::RewriteNumPadKeys(XEvent* event) {
541 DCHECK(event->type == KeyPress || event->type == KeyRelease);
591 bool rewritten = false; 542 bool rewritten = false;
592 #if defined(OS_CHROMEOS) 543 XKeyEvent* xkey = &event->xkey;
593 XEvent* xev = event->native_event();
594 XKeyEvent* xkey = &(xev->xkey);
595
596 const KeySym keysym = XLookupKeysym(xkey, 0); 544 const KeySym keysym = XLookupKeysym(xkey, 0);
597 switch (keysym) { 545 switch (keysym) {
598 case XK_KP_Insert: 546 case XK_KP_Insert:
599 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_0), 547 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_0),
600 xkey->state | Mod2Mask, 548 xkey->state | Mod2Mask);
601 ui::VKEY_NUMPAD0, event->flags());
602 rewritten = true; 549 rewritten = true;
603 break; 550 break;
604 case XK_KP_Delete: 551 case XK_KP_Delete:
605 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_Decimal), 552 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_Decimal),
606 xkey->state | Mod2Mask, 553 xkey->state | Mod2Mask);
607 ui::VKEY_DECIMAL, event->flags());
608 rewritten = true; 554 rewritten = true;
609 break; 555 break;
610 case XK_KP_End: 556 case XK_KP_End:
611 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_1), 557 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_1),
612 xkey->state | Mod2Mask, 558 xkey->state | Mod2Mask);
613 ui::VKEY_NUMPAD1, event->flags());
614 rewritten = true; 559 rewritten = true;
615 break; 560 break;
616 case XK_KP_Down: 561 case XK_KP_Down:
617 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_2), 562 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_2),
618 xkey->state | Mod2Mask, 563 xkey->state | Mod2Mask);
619 ui::VKEY_NUMPAD2, event->flags());
620 rewritten = true; 564 rewritten = true;
621 break; 565 break;
622 case XK_KP_Next: 566 case XK_KP_Next:
623 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_3), 567 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_3),
624 xkey->state | Mod2Mask, 568 xkey->state | Mod2Mask);
625 ui::VKEY_NUMPAD3, event->flags());
626 rewritten = true; 569 rewritten = true;
627 break; 570 break;
628 case XK_KP_Left: 571 case XK_KP_Left:
629 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_4), 572 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_4),
630 xkey->state | Mod2Mask, 573 xkey->state | Mod2Mask);
631 ui::VKEY_NUMPAD4, event->flags());
632 rewritten = true; 574 rewritten = true;
633 break; 575 break;
634 case XK_KP_Begin: 576 case XK_KP_Begin:
635 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_5), 577 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_5),
636 xkey->state | Mod2Mask, 578 xkey->state | Mod2Mask);
637 ui::VKEY_NUMPAD5, event->flags());
638 rewritten = true; 579 rewritten = true;
639 break; 580 break;
640 case XK_KP_Right: 581 case XK_KP_Right:
641 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_6), 582 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_6),
642 xkey->state | Mod2Mask, 583 xkey->state | Mod2Mask);
643 ui::VKEY_NUMPAD6, event->flags());
644 rewritten = true; 584 rewritten = true;
645 break; 585 break;
646 case XK_KP_Home: 586 case XK_KP_Home:
647 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_7), 587 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_7),
648 xkey->state | Mod2Mask, 588 xkey->state | Mod2Mask);
649 ui::VKEY_NUMPAD7, event->flags());
650 rewritten = true; 589 rewritten = true;
651 break; 590 break;
652 case XK_KP_Up: 591 case XK_KP_Up:
653 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_8), 592 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_8),
654 xkey->state | Mod2Mask, 593 xkey->state | Mod2Mask);
655 ui::VKEY_NUMPAD8, event->flags());
656 rewritten = true; 594 rewritten = true;
657 break; 595 break;
658 case XK_KP_Prior: 596 case XK_KP_Prior:
659 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_9), 597 OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_9),
660 xkey->state | Mod2Mask, 598 xkey->state | Mod2Mask);
661 ui::VKEY_NUMPAD9, event->flags());
662 rewritten = true; 599 rewritten = true;
663 break; 600 break;
664 case XK_KP_Divide: 601 case XK_KP_Divide:
665 case XK_KP_Multiply: 602 case XK_KP_Multiply:
666 case XK_KP_Subtract: 603 case XK_KP_Subtract:
667 case XK_KP_Add: 604 case XK_KP_Add:
668 case XK_KP_Enter: 605 case XK_KP_Enter:
669 // Add Mod2Mask for consistency. 606 // Add Mod2Mask for consistency.
670 OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask, 607 OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask);
671 event->key_code(), event->flags());
672 rewritten = true; 608 rewritten = true;
673 break; 609 break;
674 default: 610 default:
675 break; 611 break;
676 } 612 }
677 #else
678 // TODO(yusukes): Support Ash on other platforms if needed.
679 #endif
680 return rewritten; 613 return rewritten;
681 } 614 }
682 615
683 bool EventRewriter::RewriteExtendedKeys(ui::KeyEvent* event) { 616 bool EventRewriter::RewriteExtendedKeys(XEvent* event) {
684 #if defined(OS_CHROMEOS) 617 DCHECK(event->type == KeyPress || event->type == KeyRelease);
685 XEvent* xev = event->native_event(); 618 XKeyEvent* xkey = &event->xkey;
686 XKeyEvent* xkey = &(xev->xkey);
687 const KeySym keysym = XLookupKeysym(xkey, 0); 619 const KeySym keysym = XLookupKeysym(xkey, 0);
688 620
689 KeySym remapped_native_keysym = 0; 621 KeySym remapped_native_keysym = 0;
690 unsigned int remapped_native_mods = 0; 622 unsigned int remapped_native_mods = 0;
691 ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN; 623 bool rewritten = false;
692 unsigned int remapped_mods = 0;
693 624
694 if (xkey->state & Mod4Mask) { 625 if (xkey->state & Mod4Mask) {
695 // Allow Search to avoid rewriting extended keys. 626 // Allow Search to avoid rewriting extended keys.
696 static const KeyboardRemapping kAvoidRemappings[] = { 627 static const KeyboardRemapping kAvoidRemappings[] = {
697 { // Alt+Backspace 628 { // Alt+Backspace
698 XK_BackSpace, 629 XK_BackSpace, Mod1Mask | Mod4Mask,
699 ui::EF_ALT_DOWN, Mod1Mask | Mod4Mask, 630 XK_BackSpace, Mod1Mask,
700 XK_BackSpace, ui::VKEY_BACK,
701 ui::EF_ALT_DOWN, Mod1Mask,
702 }, 631 },
703 { // Control+Alt+Up 632 { // Control+Alt+Up
704 XK_Up, 633 XK_Up, Mod1Mask | ControlMask | Mod4Mask,
705 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, 634 XK_Up, Mod1Mask | ControlMask,
706 Mod1Mask | ControlMask | Mod4Mask,
707 XK_Up, ui::VKEY_UP,
708 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask,
709 }, 635 },
710 { // Alt+Up 636 { // Alt+Up
711 XK_Up, 637 XK_Up, Mod1Mask | Mod4Mask,
712 ui::EF_ALT_DOWN, Mod1Mask | Mod4Mask, 638 XK_Up, Mod1Mask,
713 XK_Up, ui::VKEY_UP,
714 ui::EF_ALT_DOWN, Mod1Mask,
715 }, 639 },
716 { // Control+Alt+Down 640 { // Control+Alt+Down
717 XK_Down, 641 XK_Down, Mod1Mask | ControlMask | Mod4Mask,
718 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, 642 XK_Down, Mod1Mask | ControlMask,
719 Mod1Mask | ControlMask | Mod4Mask,
720 XK_Down, ui::VKEY_DOWN,
721 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask,
722 }, 643 },
723 { // Alt+Down 644 { // Alt+Down
724 XK_Down, 645 XK_Down, Mod1Mask | Mod4Mask,
725 ui::EF_ALT_DOWN, Mod1Mask | Mod4Mask, 646 XK_Down, Mod1Mask,
726 XK_Down, ui::VKEY_DOWN,
727 ui::EF_ALT_DOWN, Mod1Mask,
728 } 647 }
729 }; 648 };
730 649
731 RewriteWithKeyboardRemappingsByKeySym(kAvoidRemappings, 650 rewritten = RewriteWithKeyboardRemappingsByKeySym(
732 arraysize(kAvoidRemappings), 651 kAvoidRemappings,
733 keysym, 652 arraysize(kAvoidRemappings),
734 xkey->state, 653 keysym,
735 event->flags(), 654 xkey->state,
736 &remapped_native_keysym, 655 &remapped_native_keysym,
737 &remapped_native_mods, 656 &remapped_native_mods);
738 &remapped_keycode,
739 &remapped_mods);
740 } 657 }
741 658
742 if (remapped_keycode == ui::VKEY_UNKNOWN) { 659 if (!rewritten) {
743 static const KeyboardRemapping kSearchRemappings[] = { 660 static const KeyboardRemapping kSearchRemappings[] = {
744 { // Search+BackSpace -> Delete 661 { // Search+BackSpace -> Delete
745 XK_BackSpace, 662 XK_BackSpace, Mod4Mask,
746 0, Mod4Mask, 663 XK_Delete, 0
747 XK_Delete, ui::VKEY_DELETE,
748 0, 0
749 }, 664 },
750 { // Search+Left -> Home 665 { // Search+Left -> Home
751 XK_Left, 666 XK_Left, Mod4Mask,
752 0, Mod4Mask, 667 XK_Home, 0
753 XK_Home, ui::VKEY_HOME,
754 0, 0
755 }, 668 },
756 { // Search+Up -> Prior (aka PageUp) 669 { // Search+Up -> Prior (aka PageUp)
757 XK_Up, 670 XK_Up, Mod4Mask,
758 0, Mod4Mask, 671 XK_Prior, 0
759 XK_Prior, ui::VKEY_PRIOR,
760 0, 0
761 }, 672 },
762 { // Search+Right -> End 673 { // Search+Right -> End
763 XK_Right, 674 XK_Right, Mod4Mask,
764 0, Mod4Mask, 675 XK_End, 0
765 XK_End, ui::VKEY_END,
766 0, 0
767 }, 676 },
768 { // Search+Down -> Next (aka PageDown) 677 { // Search+Down -> Next (aka PageDown)
769 XK_Down, 678 XK_Down, Mod4Mask,
770 0, Mod4Mask, 679 XK_Next, 0
771 XK_Next, ui::VKEY_NEXT,
772 0, 0
773 }, 680 },
774 { // Search+Period -> Insert 681 { // Search+Period -> Insert
775 XK_period, 682 XK_period, Mod4Mask,
776 0, Mod4Mask, 683 XK_Insert, 0
777 XK_Insert, ui::VKEY_INSERT,
778 0, 0
779 } 684 }
780 }; 685 };
781 686
782 RewriteWithKeyboardRemappingsByKeySym(kSearchRemappings, 687 rewritten = RewriteWithKeyboardRemappingsByKeySym(
783 arraysize(kSearchRemappings), 688 kSearchRemappings,
784 keysym, 689 arraysize(kSearchRemappings),
785 xkey->state, 690 keysym,
786 event->flags(), 691 xkey->state,
787 &remapped_native_keysym, 692 &remapped_native_keysym,
788 &remapped_native_mods, 693 &remapped_native_mods);
789 &remapped_keycode,
790 &remapped_mods);
791 } 694 }
792 695
793 if (remapped_keycode == ui::VKEY_UNKNOWN) { 696 if (!rewritten) {
794 static const KeyboardRemapping kNonSearchRemappings[] = { 697 static const KeyboardRemapping kNonSearchRemappings[] = {
795 { // Alt+BackSpace -> Delete 698 { // Alt+BackSpace -> Delete
796 XK_BackSpace, 699 XK_BackSpace, Mod1Mask,
797 ui::EF_ALT_DOWN, Mod1Mask, 700 XK_Delete, 0
798 XK_Delete, ui::VKEY_DELETE,
799 0, 0
800 }, 701 },
801 { // Control+Alt+Up -> Home 702 { // Control+Alt+Up -> Home
802 XK_Up, 703 XK_Up, Mod1Mask | ControlMask,
803 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask, 704 XK_Home, 0
804 XK_Home, ui::VKEY_HOME,
805 0, 0
806 }, 705 },
807 { // Alt+Up -> Prior (aka PageUp) 706 { // Alt+Up -> Prior (aka PageUp)
808 XK_Up, 707 XK_Up, Mod1Mask,
809 ui::EF_ALT_DOWN, Mod1Mask, 708 XK_Prior, 0
810 XK_Prior, ui::VKEY_PRIOR,
811 0, 0
812 }, 709 },
813 { // Control+Alt+Down -> End 710 { // Control+Alt+Down -> End
814 XK_Down, 711 XK_Down, Mod1Mask | ControlMask,
815 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, Mod1Mask | ControlMask, 712 XK_End, 0
816 XK_End, ui::VKEY_END,
817 0, 0
818 }, 713 },
819 { // Alt+Down -> Next (aka PageDown) 714 { // Alt+Down -> Next (aka PageDown)
820 XK_Down, 715 XK_Down, Mod1Mask,
821 ui::EF_ALT_DOWN, Mod1Mask, 716 XK_Next, 0
822 XK_Next, ui::VKEY_NEXT,
823 0, 0
824 } 717 }
825 }; 718 };
826 719
827 RewriteWithKeyboardRemappingsByKeySym(kNonSearchRemappings, 720 rewritten = RewriteWithKeyboardRemappingsByKeySym(
828 arraysize(kNonSearchRemappings), 721 kNonSearchRemappings,
829 keysym, 722 arraysize(kNonSearchRemappings),
830 xkey->state, 723 keysym,
831 event->flags(), 724 xkey->state,
832 &remapped_native_keysym, 725 &remapped_native_keysym,
833 &remapped_native_mods, 726 &remapped_native_mods);
834 &remapped_keycode,
835 &remapped_mods);
836 } 727 }
837 728
838 if (remapped_keycode == ui::VKEY_UNKNOWN) 729 if (!rewritten)
839 return false; 730 return false;
840 731
841 OverwriteEvent(event, 732 OverwriteEvent(event,
842 NativeKeySymToNativeKeycode(remapped_native_keysym), 733 NativeKeySymToNativeKeycode(remapped_native_keysym),
843 remapped_native_mods, 734 remapped_native_mods);
844 remapped_keycode,
845 remapped_mods);
846 return true; 735 return true;
847 #else
848 // TODO(yusukes): Support Ash on other platforms if needed.
849 return false;
850 #endif
851 } 736 }
852 737
853 bool EventRewriter::RewriteFunctionKeys(ui::KeyEvent* event) { 738 bool EventRewriter::RewriteFunctionKeys(XEvent* event) {
854 #if defined(OS_CHROMEOS) 739 DCHECK(event->type == KeyPress || event->type == KeyRelease);
855 XEvent* xev = event->native_event(); 740 XKeyEvent* xkey = &event->xkey;
856 XKeyEvent* xkey = &(xev->xkey);
857 const KeySym keysym = XLookupKeysym(xkey, 0); 741 const KeySym keysym = XLookupKeysym(xkey, 0);
858 742
859 KeySym remapped_native_keysym = 0; 743 KeySym remapped_native_keysym = 0;
860 unsigned int remapped_native_mods = 0; 744 unsigned int remapped_native_mods = 0;
861 ui::KeyboardCode remapped_keycode = ui::VKEY_UNKNOWN; 745 bool rewritten = false;
862 unsigned int remapped_mods = 0;
863 746
864 // By default the top row (F1-F12) keys are special keys for back, forward, 747 // By default the top row (F1-F12) keys are special keys for back, forward,
865 // brightness, volume, etc. However, windows for v2 apps can optionally 748 // brightness, volume, etc. However, windows for v2 apps can optionally
866 // request raw function keys for these keys. 749 // request raw function keys for these keys.
867 bool top_row_keys_are_special_keys = !TopRowKeysAreFunctionKeys(event); 750 bool top_row_keys_are_special_keys = !TopRowKeysAreFunctionKeys(event);
868 751
869 if ((xkey->state & Mod4Mask) && top_row_keys_are_special_keys) { 752 if ((xkey->state & Mod4Mask) && top_row_keys_are_special_keys) {
870 // Allow Search to avoid rewriting F1-F12. 753 // Allow Search to avoid rewriting F1-F12.
871 static const KeyboardRemapping kFkeysToFkeys[] = { 754 static const KeyboardRemapping kFkeysToFkeys[] = {
872 { XK_F1, 0, Mod4Mask, XK_F1, ui::VKEY_F1, }, 755 { XK_F1, Mod4Mask, XK_F1, },
873 { XK_F2, 0, Mod4Mask, XK_F2, ui::VKEY_F2, }, 756 { XK_F2, Mod4Mask, XK_F2, },
874 { XK_F3, 0, Mod4Mask, XK_F3, ui::VKEY_F3, }, 757 { XK_F3, Mod4Mask, XK_F3, },
875 { XK_F4, 0, Mod4Mask, XK_F4, ui::VKEY_F4, }, 758 { XK_F4, Mod4Mask, XK_F4, },
876 { XK_F5, 0, Mod4Mask, XK_F5, ui::VKEY_F5, }, 759 { XK_F5, Mod4Mask, XK_F5, },
877 { XK_F6, 0, Mod4Mask, XK_F6, ui::VKEY_F6, }, 760 { XK_F6, Mod4Mask, XK_F6, },
878 { XK_F7, 0, Mod4Mask, XK_F7, ui::VKEY_F7, }, 761 { XK_F7, Mod4Mask, XK_F7, },
879 { XK_F8, 0, Mod4Mask, XK_F8, ui::VKEY_F8, }, 762 { XK_F8, Mod4Mask, XK_F8, },
880 { XK_F9, 0, Mod4Mask, XK_F9, ui::VKEY_F9, }, 763 { XK_F9, Mod4Mask, XK_F9, },
881 { XK_F10, 0, Mod4Mask, XK_F10, ui::VKEY_F10, }, 764 { XK_F10, Mod4Mask, XK_F10, },
882 { XK_F11, 0, Mod4Mask, XK_F11, ui::VKEY_F11, }, 765 { XK_F11, Mod4Mask, XK_F11, },
883 { XK_F12, 0, Mod4Mask, XK_F12, ui::VKEY_F12, }, 766 { XK_F12, Mod4Mask, XK_F12, },
884 }; 767 };
885 768
886 RewriteWithKeyboardRemappingsByKeySym(kFkeysToFkeys, 769 rewritten = RewriteWithKeyboardRemappingsByKeySym(
887 arraysize(kFkeysToFkeys), 770 kFkeysToFkeys,
888 keysym, 771 arraysize(kFkeysToFkeys),
889 xkey->state, 772 keysym,
890 event->flags(), 773 xkey->state,
891 &remapped_native_keysym, 774 &remapped_native_keysym,
892 &remapped_native_mods, 775 &remapped_native_mods);
893 &remapped_keycode,
894 &remapped_mods);
895 } 776 }
896 777
897 if (remapped_keycode == ui::VKEY_UNKNOWN) { 778 if (!rewritten) {
898 static const KeyboardRemapping kFkeysToSpecialKeys[] = { 779 static const KeyboardRemapping kFkeysToSpecialKeys[] = {
899 { XK_F1, 0, 0, XF86XK_Back, ui::VKEY_BROWSER_BACK, 0, 0 }, 780 { XK_F1, 0, XF86XK_Back, 0 },
900 { XK_F2, 0, 0, XF86XK_Forward, ui::VKEY_BROWSER_FORWARD, 0, 0 }, 781 { XK_F2, 0, XF86XK_Forward, 0 },
901 { XK_F3, 0, 0, XF86XK_Reload, ui::VKEY_BROWSER_REFRESH, 0, 0 }, 782 { XK_F3, 0, XF86XK_Reload, 0 },
902 { XK_F4, 0, 0, XF86XK_LaunchB, ui::VKEY_MEDIA_LAUNCH_APP2, 0, 0 }, 783 { XK_F4, 0, XF86XK_LaunchB, 0 },
903 { XK_F5, 0, 0, XF86XK_LaunchA, ui::VKEY_MEDIA_LAUNCH_APP1, 0, 0 }, 784 { XK_F5, 0, XF86XK_LaunchA, 0 },
904 { XK_F6, 0, 0, XF86XK_MonBrightnessDown, ui::VKEY_BRIGHTNESS_DOWN, 0, 0 }, 785 { XK_F6, 0, XF86XK_MonBrightnessDown, 0 },
905 { XK_F7, 0, 0, XF86XK_MonBrightnessUp, ui::VKEY_BRIGHTNESS_UP, 0, 0 }, 786 { XK_F7, 0, XF86XK_MonBrightnessUp, 0 },
906 { XK_F8, 0, 0, XF86XK_AudioMute, ui::VKEY_VOLUME_MUTE, 0, 0 }, 787 { XK_F8, 0, XF86XK_AudioMute, 0 },
907 { XK_F9, 0, 0, XF86XK_AudioLowerVolume, ui::VKEY_VOLUME_DOWN, 0, 0 }, 788 { XK_F9, 0, XF86XK_AudioLowerVolume, 0 },
908 { XK_F10, 0, 0, XF86XK_AudioRaiseVolume, ui::VKEY_VOLUME_UP, 0, 0 }, 789 { XK_F10, 0, XF86XK_AudioRaiseVolume, 0 },
909 }; 790 };
910 791
911 if (top_row_keys_are_special_keys) { 792 if (top_row_keys_are_special_keys) {
912 // Rewrite the F1-F12 keys on a Chromebook keyboard to special keys. 793 // Rewrite the F1-F12 keys on a Chromebook keyboard to special keys.
913 RewriteWithKeyboardRemappingsByKeySym(kFkeysToSpecialKeys, 794 rewritten = RewriteWithKeyboardRemappingsByKeySym(
914 arraysize(kFkeysToSpecialKeys), 795 kFkeysToSpecialKeys,
915 keysym, 796 arraysize(kFkeysToSpecialKeys),
916 xkey->state, 797 keysym,
917 event->flags(), 798 xkey->state,
918 &remapped_native_keysym, 799 &remapped_native_keysym,
919 &remapped_native_mods, 800 &remapped_native_mods);
920 &remapped_keycode,
921 &remapped_mods);
922 } else if (xkey->state & Mod4Mask) { 801 } else if (xkey->state & Mod4Mask) {
923 // Use Search + F1-F12 for the special keys. 802 // Use Search + F1-F12 for the special keys.
924 RewriteWithKeyboardRemappingsByKeySym(kFkeysToSpecialKeys, 803 rewritten = RewriteWithKeyboardRemappingsByKeySym(
925 arraysize(kFkeysToSpecialKeys), 804 kFkeysToSpecialKeys,
926 keysym, 805 arraysize(kFkeysToSpecialKeys),
927 xkey->state & !Mod4Mask, 806 keysym,
928 event->flags(), 807 xkey->state & !Mod4Mask,
929 &remapped_native_keysym, 808 &remapped_native_keysym,
930 &remapped_native_mods, 809 &remapped_native_mods);
931 &remapped_keycode,
932 &remapped_mods);
933 } 810 }
934 } 811 }
935 812
936 if (remapped_keycode == ui::VKEY_UNKNOWN && xkey->state & Mod4Mask) { 813 if (!rewritten && (xkey->state & Mod4Mask)) {
937 // Remap Search+<number> to F<number>. 814 // Remap Search+<number> to F<number>.
938 // We check the keycode here instead of the keysym, as these keys have 815 // We check the keycode here instead of the keysym, as these keys have
939 // different keysyms when modifiers are pressed, such as shift. 816 // different keysyms when modifiers are pressed, such as shift.
940 817
941 // TODO(danakj): On some i18n keyboards, these choices will be bad and we 818 // TODO(danakj): On some i18n keyboards, these choices will be bad and we
942 // should make layout-specific choices here. For eg. on a french keyboard 819 // should make layout-specific choices here. For eg. on a french keyboard
943 // "-" and "6" are the same key, so F11 will not be accessible. 820 // "-" and "6" are the same key, so F11 will not be accessible.
944 static const KeyboardRemapping kNumberKeysToFkeys[] = { 821 static const KeyboardRemapping kNumberKeysToFkeys[] = {
945 { XK_1, 0, Mod4Mask, XK_F1, ui::VKEY_F1, 0, 0 }, 822 { XK_1, Mod4Mask, XK_F1, 0 },
946 { XK_2, 0, Mod4Mask, XK_F2, ui::VKEY_F2, 0, 0 }, 823 { XK_2, Mod4Mask, XK_F2, 0 },
947 { XK_3, 0, Mod4Mask, XK_F3, ui::VKEY_F3, 0, 0 }, 824 { XK_3, Mod4Mask, XK_F3, 0 },
948 { XK_4, 0, Mod4Mask, XK_F4, ui::VKEY_F4, 0, 0 }, 825 { XK_4, Mod4Mask, XK_F4, 0 },
949 { XK_5, 0, Mod4Mask, XK_F5, ui::VKEY_F5, 0, 0 }, 826 { XK_5, Mod4Mask, XK_F5, 0 },
950 { XK_6, 0, Mod4Mask, XK_F6, ui::VKEY_F6, 0, 0 }, 827 { XK_6, Mod4Mask, XK_F6, 0 },
951 { XK_7, 0, Mod4Mask, XK_F7, ui::VKEY_F7, 0, 0 }, 828 { XK_7, Mod4Mask, XK_F7, 0 },
952 { XK_8, 0, Mod4Mask, XK_F8, ui::VKEY_F8, 0, 0 }, 829 { XK_8, Mod4Mask, XK_F8, 0 },
953 { XK_9, 0, Mod4Mask, XK_F9, ui::VKEY_F9, 0, 0 }, 830 { XK_9, Mod4Mask, XK_F9, 0 },
954 { XK_0, 0, Mod4Mask, XK_F10, ui::VKEY_F10, 0, 0 }, 831 { XK_0, Mod4Mask, XK_F10, 0 },
955 { XK_minus, 0, Mod4Mask, XK_F11, ui::VKEY_F11, 0, 0 }, 832 { XK_minus, Mod4Mask, XK_F11, 0 },
956 { XK_equal, 0, Mod4Mask, XK_F12, ui::VKEY_F12, 0, 0 } 833 { XK_equal, Mod4Mask, XK_F12, 0 }
957 }; 834 };
958 835
959 RewriteWithKeyboardRemappingsByKeyCode(kNumberKeysToFkeys, 836 rewritten = RewriteWithKeyboardRemappingsByKeyCode(
960 arraysize(kNumberKeysToFkeys), 837 kNumberKeysToFkeys,
961 xkey->keycode, 838 arraysize(kNumberKeysToFkeys),
962 xkey->state, 839 xkey->keycode,
963 event->flags(), 840 xkey->state,
964 &remapped_native_keysym, 841 &remapped_native_keysym,
965 &remapped_native_mods, 842 &remapped_native_mods);
966 &remapped_keycode,
967 &remapped_mods);
968 } 843 }
969 844
970 if (remapped_keycode == ui::VKEY_UNKNOWN) 845 if (!rewritten)
971 return false; 846 return false;
972 847
973 OverwriteEvent(event, 848 OverwriteEvent(event,
974 NativeKeySymToNativeKeycode(remapped_native_keysym), 849 NativeKeySymToNativeKeycode(remapped_native_keysym),
975 remapped_native_mods, 850 remapped_native_mods);
976 remapped_keycode,
977 remapped_mods);
978 return true; 851 return true;
979 #else
980 // TODO(danakj): Support Ash on other platforms if needed.
981 return false;
982 #endif
983 } 852 }
984 853
985 void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) { 854 void EventRewriter::RewriteLocatedEvent(XEvent* event) {
986 #if defined(OS_CHROMEOS) 855 DCHECK_EQ(GenericEvent, event->type);
987 if (event->flags() & ui::EF_IS_SYNTHESIZED) 856 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
988 return;
989
990 XEvent* xevent = event->native_event();
991 if (!xevent || xevent->type != GenericEvent)
992 return;
993
994 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
995 if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease) 857 if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease)
996 return; 858 return;
997 859
998 // First, remap modifier masks. 860 // First, remap modifier masks.
999 int remapped_flags = 0;
1000 unsigned int remapped_native_modifiers = 0U; 861 unsigned int remapped_native_modifiers = 0U;
1001 GetRemappedModifierMasks(event->flags(), xievent->mods.effective, 862 GetRemappedModifierMasks(xievent->mods.effective, &remapped_native_modifiers);
1002 &remapped_flags, &remapped_native_modifiers);
1003 xievent->mods.effective = remapped_native_modifiers; 863 xievent->mods.effective = remapped_native_modifiers;
1004 864
1005 // Then, remap Alt+Button1 to Button3. 865 // Then, remap Alt+Button1 to Button3.
1006 if ((xievent->evtype == XI_ButtonPress || 866 if ((xievent->evtype == XI_ButtonPress ||
1007 pressed_device_ids_.count(xievent->sourceid)) && 867 pressed_device_ids_.count(xievent->sourceid)) &&
1008 (xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) { 868 (xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) {
1009 xievent->mods.effective &= ~Mod1Mask; 869 xievent->mods.effective &= ~Mod1Mask;
1010 xievent->detail = Button3; 870 xievent->detail = Button3;
1011 if (xievent->evtype == XI_ButtonRelease) { 871 if (xievent->evtype == XI_ButtonRelease) {
1012 // On the release clear the left button from the existing state and the 872 // On the release clear the left button from the existing state and the
1013 // mods, and set the right button. 873 // mods, and set the right button.
1014 XISetMask(xievent->buttons.mask, Button3); 874 XISetMask(xievent->buttons.mask, Button3);
1015 XIClearMask(xievent->buttons.mask, Button1); 875 XIClearMask(xievent->buttons.mask, Button1);
1016 xievent->mods.effective &= ~Button1Mask; 876 xievent->mods.effective &= ~Button1Mask;
1017 pressed_device_ids_.erase(xievent->sourceid); 877 pressed_device_ids_.erase(xievent->sourceid);
1018 } else { 878 } else {
1019 pressed_device_ids_.insert(xievent->sourceid); 879 pressed_device_ids_.insert(xievent->sourceid);
1020 } 880 }
1021 } 881 }
1022
1023 const int mouse_event_flags = event->flags() &
1024 (ui::EF_IS_DOUBLE_CLICK | ui::EF_IS_TRIPLE_CLICK | ui::EF_IS_NON_CLIENT |
1025 ui::EF_IS_SYNTHESIZED | ui::EF_FROM_TOUCH);
1026 event->set_flags(mouse_event_flags | ui::EventFlagsFromNative(xevent));
1027 #else
1028 // TODO(yusukes): Support Ash on other platforms if needed.
1029 #endif
1030 } 882 }
1031 883
1032 void EventRewriter::OverwriteEvent(ui::KeyEvent* event, 884 void EventRewriter::OverwriteEvent(XEvent* event,
1033 unsigned int new_native_keycode, 885 unsigned int new_native_keycode,
1034 unsigned int new_native_state, 886 unsigned int new_native_state) {
1035 ui::KeyboardCode new_keycode, 887 DCHECK(event->type == KeyPress || event->type == KeyRelease);
1036 int new_flags) { 888 XKeyEvent* xkey = &event->xkey;
1037 #if defined(OS_CHROMEOS)
1038 XEvent* xev = event->native_event();
1039 XKeyEvent* xkey = &(xev->xkey);
1040 xkey->keycode = new_native_keycode; 889 xkey->keycode = new_native_keycode;
1041 xkey->state = new_native_state; 890 xkey->state = new_native_state;
1042 event->set_key_code(new_keycode);
1043 event->set_character(ui::GetCharacterFromKeyCode(event->key_code(),
1044 new_flags));
1045 event->set_flags(new_flags);
1046 event->NormalizeFlags();
1047 #else
1048 // TODO(yusukes): Support Ash on other platforms if needed.
1049 #endif
1050 } 891 }
1051 892
1052 EventRewriter::DeviceType EventRewriter::DeviceAddedInternal( 893 EventRewriter::DeviceType EventRewriter::DeviceAddedInternal(
1053 int device_id, 894 int device_id,
1054 const std::string& device_name) { 895 const std::string& device_name) {
1055 const DeviceType type = EventRewriter::GetDeviceType(device_name); 896 const DeviceType type = EventRewriter::GetDeviceType(device_name);
1056 if (type == kDeviceAppleKeyboard) { 897 if (type == kDeviceAppleKeyboard) {
1057 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " 898 VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
1058 << "id=" << device_id; 899 << "id=" << device_id;
1059 } 900 }
1060 // Always overwrite the existing device_id since the X server may reuse a 901 // Always overwrite the existing device_id since the X server may reuse a
1061 // device id for an unattached device. 902 // device id for an unattached device.
1062 device_id_to_type_[device_id] = type; 903 device_id_to_type_[device_id] = type;
1063 return type; 904 return type;
1064 } 905 }
906
907 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/event_rewriter.h ('k') | chrome/browser/chromeos/event_rewriter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698