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

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

Powered by Google App Engine
This is Rietveld 408576698