OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 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/views/ash/key_rewriter.h" | 5 #include "chrome/browser/ui/views/ash/key_rewriter.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 found_apple = true; | 75 found_apple = true; |
76 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard")) | 76 if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard")) |
77 found_keyboard = true; | 77 found_keyboard = true; |
78 if (found_apple && found_keyboard) | 78 if (found_apple && found_keyboard) |
79 return kDeviceAppleKeyboard; | 79 return kDeviceAppleKeyboard; |
80 } | 80 } |
81 | 81 |
82 return kDeviceUnknown; | 82 return kDeviceUnknown; |
83 } | 83 } |
84 | 84 |
85 void KeyRewriter::RewriteCommandToControlForTesting(aura::KeyEvent* event) { | 85 void KeyRewriter::RewriteForTesting(aura::KeyEvent* event) { |
86 RewriteCommandToControl(event); | 86 Rewrite(event); |
87 } | |
88 | |
89 void KeyRewriter::RewriteNumPadKeysForTesting(aura::KeyEvent* event) { | |
90 RewriteNumPadKeys(event); | |
91 } | 87 } |
92 | 88 |
93 ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterKeyEvent( | 89 ash::KeyRewriterDelegate::Action KeyRewriter::RewriteOrFilterKeyEvent( |
94 aura::KeyEvent* event) { | 90 aura::KeyEvent* event) { |
95 const ash::KeyRewriterDelegate::Action kActionRewrite = | 91 const ash::KeyRewriterDelegate::Action kActionRewrite = |
96 ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; | 92 ash::KeyRewriterDelegate::ACTION_REWRITE_EVENT; |
97 if (!event->HasNativeEvent()) { | 93 if (!event->HasNativeEvent()) { |
98 // Do not handle a fabricated event generated by tests. | 94 // Do not handle a fabricated event generated by tests. |
99 return kActionRewrite; | 95 return kActionRewrite; |
100 } | 96 } |
101 | 97 Rewrite(event); |
102 if (RewriteCommandToControl(event)) | |
103 return kActionRewrite; | |
104 if (RewriteNumPadKeys(event)) | |
105 return kActionRewrite; | |
106 | |
107 // TODO(yusukes): Implement crbug.com/115112 (Search/Ctrl/Alt remapping) and | |
108 // crosbug.com/27167 (allow sending function keys) here. | |
109 | |
110 return kActionRewrite; // Do not drop the event. | 98 return kActionRewrite; // Do not drop the event. |
111 } | 99 } |
112 | 100 |
113 void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { | 101 void KeyRewriter::OnKeyboardMappingChanged(const aura::RootWindow* root) { |
114 #if defined(OS_CHROMEOS) | 102 #if defined(OS_CHROMEOS) |
115 RefreshKeycodes(); | 103 RefreshKeycodes(); |
116 #endif | 104 #endif |
117 } | 105 } |
118 | 106 |
119 #if defined(OS_CHROMEOS) | 107 #if defined(OS_CHROMEOS) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4); | 162 kp_4_xkeycode_ = XKeysymToKeycode(display, XK_KP_4); |
175 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5); | 163 kp_5_xkeycode_ = XKeysymToKeycode(display, XK_KP_5); |
176 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6); | 164 kp_6_xkeycode_ = XKeysymToKeycode(display, XK_KP_6); |
177 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7); | 165 kp_7_xkeycode_ = XKeysymToKeycode(display, XK_KP_7); |
178 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8); | 166 kp_8_xkeycode_ = XKeysymToKeycode(display, XK_KP_8); |
179 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9); | 167 kp_9_xkeycode_ = XKeysymToKeycode(display, XK_KP_9); |
180 kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal); | 168 kp_decimal_xkeycode_ = XKeysymToKeycode(display, XK_KP_Decimal); |
181 } | 169 } |
182 #endif | 170 #endif |
183 | 171 |
| 172 void KeyRewriter::Rewrite(aura::KeyEvent* event) { |
| 173 RewriteCommandToControl(event); |
| 174 RewriteNumPadKeys(event); |
| 175 // TODO(yusukes): Implement crbug.com/115112 (Search/Ctrl/Alt remapping) and |
| 176 // crosbug.com/27167 (allow sending function keys) here. |
| 177 } |
| 178 |
184 bool KeyRewriter::RewriteCommandToControl(aura::KeyEvent* event) { | 179 bool KeyRewriter::RewriteCommandToControl(aura::KeyEvent* event) { |
185 bool rewritten = false; | 180 bool rewritten = false; |
186 if (last_device_id_ == kBadDeviceId) | 181 if (last_device_id_ == kBadDeviceId) |
187 return rewritten; | 182 return rewritten; |
188 | 183 |
189 // Check which device generated |event|. | 184 // Check which device generated |event|. |
190 std::map<int, DeviceType>::const_iterator iter = | 185 std::map<int, DeviceType>::const_iterator iter = |
191 device_id_to_type_.find(last_device_id_); | 186 device_id_to_type_.find(last_device_id_); |
192 if (iter == device_id_to_type_.end()) { | 187 if (iter == device_id_to_type_.end()) { |
193 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; | 188 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; |
194 return rewritten; | 189 return rewritten; |
195 } | 190 } |
196 | 191 |
197 const DeviceType type = iter->second; | 192 const DeviceType type = iter->second; |
198 if (type != kDeviceAppleKeyboard) | 193 if (type != kDeviceAppleKeyboard) |
199 return rewritten; | 194 return rewritten; |
200 | 195 |
201 #if defined(OS_CHROMEOS) | 196 #if defined(OS_CHROMEOS) |
202 XEvent* xev = event->native_event(); | 197 XEvent* xev = event->native_event(); |
203 XKeyEvent* xkey = &(xev->xkey); | 198 XKeyEvent* xkey = &(xev->xkey); |
204 | 199 |
205 // Mod4 is the Windows key on a PC keyboard or Command key on an Apple | 200 // Mod4 is the Windows key on a PC keyboard or Command key on an Apple |
206 // keyboard. | 201 // keyboard. |
207 if (xkey->state & Mod4Mask) { | 202 if (xkey->state & Mod4Mask) { |
208 xkey->state &= ~Mod4Mask; | 203 xkey->state &= ~Mod4Mask; |
209 xkey->state |= ControlMask; | 204 xkey->state |= ControlMask; |
210 event->set_flags(event->flags() | ui::EF_CONTROL_DOWN); | 205 event->set_flags(event->flags() | ui::EF_CONTROL_DOWN); |
| 206 rewritten = true; |
211 } | 207 } |
212 | 208 |
213 const KeySym keysym = XLookupKeysym(xkey, 0); | 209 const KeySym keysym = XLookupKeysym(xkey, 0); |
214 switch (keysym) { | 210 switch (keysym) { |
215 case XK_Super_L: | 211 case XK_Super_L: |
216 // left Command -> left Control | 212 // left Command -> left Control |
217 Rewrite(event, control_l_xkeycode_, xkey->state, | 213 OverwriteEvent(event, control_l_xkeycode_, xkey->state, |
218 ui::VKEY_LCONTROL, event->flags()); | 214 ui::VKEY_CONTROL, event->flags()); |
219 rewritten = true; | 215 rewritten = true; |
220 break; | 216 break; |
221 case XK_Super_R: | 217 case XK_Super_R: |
222 // right Command -> right Control | 218 // right Command -> right Control |
223 Rewrite(event, control_r_xkeycode_, xkey->state, | 219 OverwriteEvent(event, control_r_xkeycode_, xkey->state, |
224 ui::VKEY_RCONTROL, event->flags()); | 220 ui::VKEY_CONTROL, event->flags()); |
225 rewritten = true; | 221 rewritten = true; |
226 break; | 222 break; |
227 default: | 223 default: |
228 break; | 224 break; |
229 } | 225 } |
230 | 226 |
231 DCHECK_NE(ui::VKEY_LWIN, ui::KeyboardCodeFromXKeyEvent(xev)); | 227 DCHECK_NE(ui::VKEY_LWIN, ui::KeyboardCodeFromXKeyEvent(xev)); |
232 DCHECK_NE(ui::VKEY_RWIN, ui::KeyboardCodeFromXKeyEvent(xev)); | 228 DCHECK_NE(ui::VKEY_RWIN, ui::KeyboardCodeFromXKeyEvent(xev)); |
233 #else | 229 #else |
234 // TODO(yusukes): Support Ash on other platforms if needed. | 230 // TODO(yusukes): Support Ash on other platforms if needed. |
235 #endif | 231 #endif |
236 return rewritten; | 232 return rewritten; |
237 } | 233 } |
238 | 234 |
239 bool KeyRewriter::RewriteNumPadKeys(aura::KeyEvent* event) { | 235 bool KeyRewriter::RewriteNumPadKeys(aura::KeyEvent* event) { |
240 bool rewritten = false; | 236 bool rewritten = false; |
241 #if defined(OS_CHROMEOS) | 237 #if defined(OS_CHROMEOS) |
242 XEvent* xev = event->native_event(); | 238 XEvent* xev = event->native_event(); |
243 XKeyEvent* xkey = &(xev->xkey); | 239 XKeyEvent* xkey = &(xev->xkey); |
244 | 240 |
245 const KeySym keysym = XLookupKeysym(xkey, 0); | 241 const KeySym keysym = XLookupKeysym(xkey, 0); |
246 switch (keysym) { | 242 switch (keysym) { |
247 case XK_KP_Insert: | 243 case XK_KP_Insert: |
248 Rewrite(event, kp_0_xkeycode_, xkey->state | Mod2Mask, | 244 OverwriteEvent(event, kp_0_xkeycode_, xkey->state | Mod2Mask, |
249 ui::VKEY_NUMPAD0, event->flags()); | 245 ui::VKEY_NUMPAD0, event->flags()); |
250 rewritten = true; | 246 rewritten = true; |
251 break; | 247 break; |
252 case XK_KP_Delete: | 248 case XK_KP_Delete: |
253 Rewrite(event, kp_decimal_xkeycode_, xkey->state | Mod2Mask, | 249 OverwriteEvent(event, kp_decimal_xkeycode_, xkey->state | Mod2Mask, |
254 ui::VKEY_DECIMAL, event->flags()); | 250 ui::VKEY_DECIMAL, event->flags()); |
255 rewritten = true; | 251 rewritten = true; |
256 break; | 252 break; |
257 case XK_KP_End: | 253 case XK_KP_End: |
258 Rewrite(event, kp_1_xkeycode_, xkey->state | Mod2Mask, | 254 OverwriteEvent(event, kp_1_xkeycode_, xkey->state | Mod2Mask, |
259 ui::VKEY_NUMPAD1, event->flags()); | 255 ui::VKEY_NUMPAD1, event->flags()); |
260 rewritten = true; | 256 rewritten = true; |
261 break; | 257 break; |
262 case XK_KP_Down: | 258 case XK_KP_Down: |
263 Rewrite(event, kp_2_xkeycode_, xkey->state | Mod2Mask, | 259 OverwriteEvent(event, kp_2_xkeycode_, xkey->state | Mod2Mask, |
264 ui::VKEY_NUMPAD2, event->flags()); | 260 ui::VKEY_NUMPAD2, event->flags()); |
265 rewritten = true; | 261 rewritten = true; |
266 break; | 262 break; |
267 case XK_KP_Next: | 263 case XK_KP_Next: |
268 Rewrite(event, kp_3_xkeycode_, xkey->state | Mod2Mask, | 264 OverwriteEvent(event, kp_3_xkeycode_, xkey->state | Mod2Mask, |
269 ui::VKEY_NUMPAD3, event->flags()); | 265 ui::VKEY_NUMPAD3, event->flags()); |
270 rewritten = true; | 266 rewritten = true; |
271 break; | 267 break; |
272 case XK_KP_Left: | 268 case XK_KP_Left: |
273 Rewrite(event, kp_4_xkeycode_, xkey->state | Mod2Mask, | 269 OverwriteEvent(event, kp_4_xkeycode_, xkey->state | Mod2Mask, |
274 ui::VKEY_NUMPAD4, event->flags()); | 270 ui::VKEY_NUMPAD4, event->flags()); |
275 rewritten = true; | 271 rewritten = true; |
276 break; | 272 break; |
277 case XK_KP_Begin: | 273 case XK_KP_Begin: |
278 Rewrite(event, kp_5_xkeycode_, xkey->state | Mod2Mask, | 274 OverwriteEvent(event, kp_5_xkeycode_, xkey->state | Mod2Mask, |
279 ui::VKEY_NUMPAD5, event->flags()); | 275 ui::VKEY_NUMPAD5, event->flags()); |
280 rewritten = true; | 276 rewritten = true; |
281 break; | 277 break; |
282 case XK_KP_Right: | 278 case XK_KP_Right: |
283 Rewrite(event, kp_6_xkeycode_, xkey->state | Mod2Mask, | 279 OverwriteEvent(event, kp_6_xkeycode_, xkey->state | Mod2Mask, |
284 ui::VKEY_NUMPAD6, event->flags()); | 280 ui::VKEY_NUMPAD6, event->flags()); |
285 rewritten = true; | 281 rewritten = true; |
286 break; | 282 break; |
287 case XK_KP_Home: | 283 case XK_KP_Home: |
288 Rewrite(event, kp_7_xkeycode_, xkey->state | Mod2Mask, | 284 OverwriteEvent(event, kp_7_xkeycode_, xkey->state | Mod2Mask, |
289 ui::VKEY_NUMPAD7, event->flags()); | 285 ui::VKEY_NUMPAD7, event->flags()); |
290 rewritten = true; | 286 rewritten = true; |
291 break; | 287 break; |
292 case XK_KP_Up: | 288 case XK_KP_Up: |
293 Rewrite(event, kp_8_xkeycode_, xkey->state | Mod2Mask, | 289 OverwriteEvent(event, kp_8_xkeycode_, xkey->state | Mod2Mask, |
294 ui::VKEY_NUMPAD8, event->flags()); | 290 ui::VKEY_NUMPAD8, event->flags()); |
295 rewritten = true; | 291 rewritten = true; |
296 break; | 292 break; |
297 case XK_KP_Prior: | 293 case XK_KP_Prior: |
298 Rewrite(event, kp_9_xkeycode_, xkey->state | Mod2Mask, | 294 OverwriteEvent(event, kp_9_xkeycode_, xkey->state | Mod2Mask, |
299 ui::VKEY_NUMPAD9, event->flags()); | 295 ui::VKEY_NUMPAD9, event->flags()); |
300 rewritten = true; | 296 rewritten = true; |
301 break; | 297 break; |
302 case XK_KP_Divide: | 298 case XK_KP_Divide: |
303 case XK_KP_Multiply: | 299 case XK_KP_Multiply: |
304 case XK_KP_Subtract: | 300 case XK_KP_Subtract: |
305 case XK_KP_Add: | 301 case XK_KP_Add: |
306 case XK_KP_Enter: | 302 case XK_KP_Enter: |
307 // Add Mod2Mask for consistency. | 303 // Add Mod2Mask for consistency. |
308 Rewrite(event, xkey->keycode, xkey->state | Mod2Mask, | 304 OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask, |
309 event->key_code(), event->flags()); | 305 event->key_code(), event->flags()); |
310 rewritten = true; | 306 rewritten = true; |
311 break; | 307 break; |
312 default: | 308 default: |
313 break; | 309 break; |
314 } | 310 } |
315 #else | 311 #else |
316 // TODO(yusukes): Support Ash on other platforms if needed. | 312 // TODO(yusukes): Support Ash on other platforms if needed. |
317 #endif | 313 #endif |
318 return rewritten; | 314 return rewritten; |
319 } | 315 } |
320 | 316 |
321 void KeyRewriter::Rewrite(aura::KeyEvent* event, | 317 void KeyRewriter::OverwriteEvent(aura::KeyEvent* event, |
322 unsigned int new_native_keycode, | 318 unsigned int new_native_keycode, |
323 unsigned int new_native_state, | 319 unsigned int new_native_state, |
324 ui::KeyboardCode new_keycode, | 320 ui::KeyboardCode new_keycode, |
325 int new_flags) { | 321 int new_flags) { |
326 #if defined(OS_CHROMEOS) | 322 #if defined(OS_CHROMEOS) |
327 XEvent* xev = event->native_event(); | 323 XEvent* xev = event->native_event(); |
328 XKeyEvent* xkey = &(xev->xkey); | 324 XKeyEvent* xkey = &(xev->xkey); |
329 xkey->keycode = new_native_keycode; | 325 xkey->keycode = new_native_keycode; |
330 xkey->state = new_native_state; | 326 xkey->state = new_native_state; |
331 event->set_key_code(new_keycode); | 327 event->set_key_code(new_keycode); |
332 event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), | 328 event->set_character(ui::GetCharacterFromKeyCode(event->key_code(), |
333 new_flags)); | 329 new_flags)); |
334 event->set_flags(new_flags); | 330 event->set_flags(new_flags); |
335 #else | 331 #else |
336 // TODO(yusukes): Support Ash on other platforms if needed. | 332 // TODO(yusukes): Support Ash on other platforms if needed. |
337 #endif | 333 #endif |
338 } | 334 } |
339 | 335 |
340 KeyRewriter::DeviceType KeyRewriter::DeviceAddedInternal( | 336 KeyRewriter::DeviceType KeyRewriter::DeviceAddedInternal( |
341 int device_id, | 337 int device_id, |
342 const std::string& device_name) { | 338 const std::string& device_name) { |
343 const DeviceType type = KeyRewriter::GetDeviceType(device_name); | 339 const DeviceType type = KeyRewriter::GetDeviceType(device_name); |
344 if (type == kDeviceAppleKeyboard) { | 340 if (type == kDeviceAppleKeyboard) { |
345 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " | 341 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " |
346 << "id=" << device_id; | 342 << "id=" << device_id; |
347 } | 343 } |
348 // Always overwrite the existing device_id since the X server may reuse a | 344 // Always overwrite the existing device_id since the X server may reuse a |
349 // device id for an unattached device. | 345 // device id for an unattached device. |
350 device_id_to_type_[device_id] = type; | 346 device_id_to_type_[device_id] = type; |
351 return type; | 347 return type; |
352 } | 348 } |
OLD | NEW |