OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/events/event_rewriter.h" | 5 #include "chrome/browser/chromeos/events/event_rewriter.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "ash/sticky_keys/sticky_keys_controller.h" | 9 #include "ash/sticky_keys/sticky_keys_controller.h" |
10 #include "ash/wm/window_state.h" | 10 #include "ash/wm/window_state.h" |
11 #include "ash/wm/window_util.h" | 11 #include "ash/wm/window_util.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/prefs/pref_service.h" | 15 #include "base/prefs/pref_service.h" |
16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
17 #include "base/sys_info.h" | 17 #include "base/sys_info.h" |
18 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" | 18 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" |
19 #include "chrome/browser/chromeos/login/users/user_manager.h" | 19 #include "chrome/browser/chromeos/login/users/user_manager.h" |
20 #include "chrome/browser/profiles/profile_manager.h" | 20 #include "chrome/browser/profiles/profile_manager.h" |
21 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
22 #include "chromeos/chromeos_switches.h" | 22 #include "chromeos/chromeos_switches.h" |
23 #include "chromeos/ime/ime_keyboard.h" | 23 #include "chromeos/ime/ime_keyboard.h" |
24 #include "chromeos/ime/input_method_manager.h" | 24 #include "chromeos/ime/input_method_manager.h" |
25 #include "ui/events/event.h" | 25 #include "ui/events/event.h" |
26 #include "ui/events/event_utils.h" | 26 #include "ui/events/event_utils.h" |
27 #include "ui/events/keycodes/keyboard_code_conversion.h" | 27 #include "ui/events/keycodes/keyboard_code_conversion.h" |
28 #include "ui/events/platform/platform_event_source.h" | |
29 #include "ui/wm/core/window_util.h" | 28 #include "ui/wm/core/window_util.h" |
30 | 29 |
31 #if defined(USE_X11) | 30 #if defined(USE_X11) |
32 #include <X11/extensions/XInput2.h> | 31 #include <X11/extensions/XInput2.h> |
33 #include <X11/Xlib.h> | 32 #include <X11/Xlib.h> |
34 // Get rid of macros from Xlib.h that conflicts with other parts of the code. | 33 // Get rid of macros from Xlib.h that conflicts with other parts of the code. |
35 #undef RootWindow | 34 #undef RootWindow |
36 #undef Status | 35 #undef Status |
37 | 36 |
38 #include "chrome/browser/chromeos/events/xinput_hierarchy_changed_event_listener
.h" | |
39 #include "ui/base/x/x11_util.h" | 37 #include "ui/base/x/x11_util.h" |
40 #include "ui/events/keycodes/keyboard_code_conversion_x.h" | 38 #include "ui/events/keycodes/keyboard_code_conversion_x.h" |
41 #endif | 39 #endif |
42 | 40 |
43 namespace chromeos { | 41 namespace chromeos { |
44 | 42 |
45 namespace { | 43 namespace { |
46 | 44 |
47 const int kBadDeviceId = -1; | |
48 | |
49 // Table of key properties of remappable keys and/or remapping targets. | 45 // Table of key properties of remappable keys and/or remapping targets. |
50 // This is searched in two distinct ways: | 46 // This is searched in two distinct ways: |
51 // - |remap_to| is an |input_method::ModifierKey|, which is the form | 47 // - |remap_to| is an |input_method::ModifierKey|, which is the form |
52 // held in user preferences. |GetRemappedKey()| maps this to the | 48 // held in user preferences. |GetRemappedKey()| maps this to the |
53 // corresponding |key_code| and characterstic event |flag|. | 49 // corresponding |key_code| and characterstic event |flag|. |
54 // - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this | 50 // - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this |
55 // to the corresponding user preference |pref_name| for that flag's | 51 // to the corresponding user preference |pref_name| for that flag's |
56 // key, so that it can then be remapped as above. | 52 // key, so that it can then be remapped as above. |
57 // In addition |kModifierRemappingCtrl| is a direct reference to the | 53 // In addition |kModifierRemappingCtrl| is a direct reference to the |
58 // Control key entry in the table, used in handling Chromebook Diamond | 54 // Control key entry in the table, used in handling Chromebook Diamond |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 {ui::EF_MIDDLE_MOUSE_BUTTON, Button2Mask}, | 142 {ui::EF_MIDDLE_MOUSE_BUTTON, Button2Mask}, |
147 {ui::EF_RIGHT_MOUSE_BUTTON, Button3Mask}, | 143 {ui::EF_RIGHT_MOUSE_BUTTON, Button3Mask}, |
148 }; | 144 }; |
149 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) { | 145 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) { |
150 if (ui_flags & flags[i].ui) | 146 if (ui_flags & flags[i].ui) |
151 *x_flags |= flags[i].x; | 147 *x_flags |= flags[i].x; |
152 else | 148 else |
153 *x_flags &= ~flags[i].x; | 149 *x_flags &= ~flags[i].x; |
154 } | 150 } |
155 } | 151 } |
156 #endif | 152 |
| 153 void UpdateX11Button(int ui_flag, unsigned int* x_button) { |
| 154 switch (ui_flag) { |
| 155 case ui::EF_LEFT_MOUSE_BUTTON: |
| 156 *x_button = Button1; |
| 157 break; |
| 158 case ui::EF_MIDDLE_MOUSE_BUTTON: |
| 159 *x_button = Button2; |
| 160 break; |
| 161 case ui::EF_RIGHT_MOUSE_BUTTON: |
| 162 *x_button = Button3; |
| 163 break; |
| 164 } |
| 165 } |
| 166 #endif // defined(USE_X11) |
157 | 167 |
158 bool IsSendEvent(const ui::Event& event) { | 168 bool IsSendEvent(const ui::Event& event) { |
159 #if defined(USE_X11) | 169 #if defined(USE_X11) |
160 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See | 170 // Do not rewrite an event sent by ui_controls::SendKeyPress(). See |
161 // crbug.com/136465. | 171 // crbug.com/136465. |
162 XEvent* xev = event.native_event(); | 172 XEvent* xev = event.native_event(); |
163 if (xev && xev->xany.send_event) | 173 if (xev && xev->xany.send_event) |
164 return true; | 174 return true; |
165 #endif | 175 #endif |
166 return false; | 176 return false; |
167 } | 177 } |
168 | 178 |
169 } // namespace | 179 } // namespace |
170 | 180 |
171 EventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller) | 181 EventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller) |
172 : last_device_id_(kBadDeviceId), | 182 : last_keyboard_device_id_(ui::ED_UNKNOWN_DEVICE), |
173 ime_keyboard_for_testing_(NULL), | 183 ime_keyboard_for_testing_(NULL), |
174 pref_service_for_testing_(NULL), | 184 pref_service_for_testing_(NULL), |
175 sticky_keys_controller_(sticky_keys_controller) { | 185 sticky_keys_controller_(sticky_keys_controller) { |
176 #if defined(USE_X11) | |
177 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); | |
178 if (base::SysInfo::IsRunningOnChromeOS()) { | |
179 XInputHierarchyChangedEventListener::GetInstance()->AddObserver(this); | |
180 } | |
181 #endif | |
182 } | 186 } |
183 | 187 |
184 EventRewriter::~EventRewriter() { | 188 EventRewriter::~EventRewriter() { |
185 #if defined(USE_X11) | |
186 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); | |
187 if (base::SysInfo::IsRunningOnChromeOS()) { | |
188 XInputHierarchyChangedEventListener::GetInstance()->RemoveObserver(this); | |
189 } | |
190 #endif | |
191 } | 189 } |
192 | 190 |
193 EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting( | 191 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedForTesting( |
194 int device_id, | 192 int device_id, |
195 const std::string& device_name) { | 193 const std::string& device_name) { |
196 return DeviceAddedInternal(device_id, device_name); | 194 // Tests must avoid XI2 reserved device IDs. |
| 195 DCHECK((device_id < 0) || (device_id > 1)); |
| 196 return KeyboardDeviceAddedInternal(device_id, device_name); |
197 } | 197 } |
198 | 198 |
199 void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event, | 199 void EventRewriter::RewriteMouseButtonEventForTesting( |
200 int* flags) { | 200 const ui::MouseEvent& event, |
201 RewriteLocatedEvent(event, flags); | 201 scoped_ptr<ui::Event>* rewritten_event) { |
| 202 RewriteMouseButtonEvent(event, rewritten_event); |
202 } | 203 } |
203 | 204 |
204 ui::EventRewriteStatus EventRewriter::RewriteEvent( | 205 ui::EventRewriteStatus EventRewriter::RewriteEvent( |
205 const ui::Event& event, | 206 const ui::Event& event, |
206 scoped_ptr<ui::Event>* rewritten_event) { | 207 scoped_ptr<ui::Event>* rewritten_event) { |
207 if ((event.type() == ui::ET_KEY_PRESSED) || | 208 if ((event.type() == ui::ET_KEY_PRESSED) || |
208 (event.type() == ui::ET_KEY_RELEASED)) { | 209 (event.type() == ui::ET_KEY_RELEASED)) { |
209 return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event), | 210 return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event), |
210 rewritten_event); | 211 rewritten_event); |
211 } | 212 } |
(...skipping 26 matching lines...) Expand all Loading... |
238 // modifier key releases that match the ones previously discarded. So, we | 239 // modifier key releases that match the ones previously discarded. So, we |
239 // know that they don't have to be passed through the post-sticky key | 240 // know that they don't have to be passed through the post-sticky key |
240 // rewriting phases, |RewriteExtendedKeys()| and |RewriteFunctionKeys()|, | 241 // rewriting phases, |RewriteExtendedKeys()| and |RewriteFunctionKeys()|, |
241 // because those phases do nothing with modifier key releases. | 242 // because those phases do nothing with modifier key releases. |
242 return sticky_keys_controller_->NextDispatchEvent(new_event); | 243 return sticky_keys_controller_->NextDispatchEvent(new_event); |
243 } | 244 } |
244 NOTREACHED(); | 245 NOTREACHED(); |
245 return ui::EVENT_REWRITE_CONTINUE; | 246 return ui::EVENT_REWRITE_CONTINUE; |
246 } | 247 } |
247 | 248 |
| 249 void EventRewriter::BuildRewrittenKeyEvent( |
| 250 const ui::KeyEvent& key_event, |
| 251 ui::KeyboardCode key_code, |
| 252 int flags, |
| 253 scoped_ptr<ui::Event>* rewritten_event) { |
| 254 ui::KeyEvent* rewritten_key_event = NULL; |
248 #if defined(USE_X11) | 255 #if defined(USE_X11) |
| 256 XEvent* xev = key_event.native_event(); |
| 257 if (xev) { |
| 258 XEvent xkeyevent; |
| 259 // Convert all XI2-based key events into X11 core-based key events, |
| 260 // until consumers no longer depend on receiving X11 core events. |
| 261 if (xev->type == GenericEvent) |
| 262 ui::InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent); |
| 263 else |
| 264 xkeyevent.xkey = xev->xkey; |
| 265 |
| 266 // Update native event to match rewritten |ui::Event|. |
| 267 xkeyevent.xkey.keycode = XKeysymToKeycode( |
| 268 gfx::GetXDisplay(), |
| 269 ui::XKeysymForWindowsKeyCode(key_code, flags & ui::EF_SHIFT_DOWN)); |
| 270 UpdateX11EventMask(flags, &xkeyevent.xkey.state); |
| 271 ui::KeyEvent x11_key_event(&xkeyevent, false); |
| 272 rewritten_key_event = new ui::KeyEvent(x11_key_event); |
| 273 } |
| 274 #endif |
| 275 if (!rewritten_key_event) |
| 276 rewritten_key_event = new ui::KeyEvent(key_event); |
| 277 rewritten_key_event->set_flags(flags); |
| 278 rewritten_key_event->set_key_code(key_code); |
| 279 rewritten_key_event->set_character( |
| 280 ui::GetCharacterFromKeyCode(key_code, flags)); |
| 281 rewritten_key_event->NormalizeFlags(); |
| 282 rewritten_event->reset(rewritten_key_event); |
| 283 } |
| 284 |
249 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) { | 285 void EventRewriter::DeviceKeyPressedOrReleased(int device_id) { |
250 if (!device_id_to_type_.count(device_id)) { | 286 if (!device_id_to_type_.count(device_id)) |
251 // |device_id| is unknown. This means the device was connected before | 287 KeyboardDeviceAdded(device_id); |
252 // booting the OS. Query the name of the device and add it to the map. | 288 last_keyboard_device_id_ = device_id; |
253 DeviceAdded(device_id); | |
254 } | |
255 last_device_id_ = device_id; | |
256 } | 289 } |
257 #endif | |
258 | 290 |
259 const PrefService* EventRewriter::GetPrefService() const { | 291 const PrefService* EventRewriter::GetPrefService() const { |
260 if (pref_service_for_testing_) | 292 if (pref_service_for_testing_) |
261 return pref_service_for_testing_; | 293 return pref_service_for_testing_; |
262 Profile* profile = ProfileManager::GetActiveUserProfile(); | 294 Profile* profile = ProfileManager::GetActiveUserProfile(); |
263 return profile ? profile->GetPrefs() : NULL; | 295 return profile ? profile->GetPrefs() : NULL; |
264 } | 296 } |
265 | 297 |
266 bool EventRewriter::IsAppleKeyboard() const { | 298 bool EventRewriter::IsAppleKeyboard() const { |
267 if (last_device_id_ == kBadDeviceId) | 299 if (last_keyboard_device_id_ == ui::ED_UNKNOWN_DEVICE) |
268 return false; | 300 return false; |
269 | 301 |
270 // Check which device generated |event|. | 302 // Check which device generated |event|. |
271 std::map<int, DeviceType>::const_iterator iter = | 303 std::map<int, DeviceType>::const_iterator iter = |
272 device_id_to_type_.find(last_device_id_); | 304 device_id_to_type_.find(last_keyboard_device_id_); |
273 if (iter == device_id_to_type_.end()) { | 305 if (iter == device_id_to_type_.end()) { |
274 LOG(ERROR) << "Device ID " << last_device_id_ << " is unknown."; | 306 LOG(ERROR) << "Device ID " << last_keyboard_device_id_ << " is unknown."; |
275 return false; | 307 return false; |
276 } | 308 } |
277 | 309 |
278 const DeviceType type = iter->second; | 310 const DeviceType type = iter->second; |
279 return type == kDeviceAppleKeyboard; | 311 return type == kDeviceAppleKeyboard; |
280 } | 312 } |
281 | 313 |
282 bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const { | 314 bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const { |
283 const PrefService* prefs = GetPrefService(); | 315 const PrefService* prefs = GetPrefService(); |
284 if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) && | 316 if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) && |
285 prefs->GetBoolean(prefs::kLanguageSendFunctionKeys)) | 317 prefs->GetBoolean(prefs::kLanguageSendFunctionKeys)) |
286 return true; | 318 return true; |
287 | 319 |
288 ash::wm::WindowState* state = ash::wm::GetActiveWindowState(); | 320 ash::wm::WindowState* state = ash::wm::GetActiveWindowState(); |
289 return state ? state->top_row_keys_are_function_keys() : false; | 321 return state ? state->top_row_keys_are_function_keys() : false; |
290 } | 322 } |
291 | 323 |
292 int EventRewriter::GetRemappedModifierMasks(const PrefService& pref_service, | 324 int EventRewriter::GetRemappedModifierMasks(const PrefService& pref_service, |
293 const ui::Event& event, | 325 const ui::Event& event, |
294 int original_flags) const { | 326 int original_flags) const { |
295 int unmodified_flags = original_flags; | 327 int unmodified_flags = original_flags; |
296 int rewritten_flags = 0; | 328 int rewritten_flags = 0; |
297 for (size_t i = 0; unmodified_flags && (i < arraysize(kModifierRemappings)); | 329 for (size_t i = 0; unmodified_flags && (i < arraysize(kModifierRemappings)); |
298 ++i) { | 330 ++i) { |
299 const ModifierRemapping* remapped_key = 0; | 331 const ModifierRemapping* remapped_key = NULL; |
300 if (!(unmodified_flags & kModifierRemappings[i].flag)) | 332 if (!(unmodified_flags & kModifierRemappings[i].flag)) |
301 continue; | 333 continue; |
302 switch (kModifierRemappings[i].flag) { | 334 switch (kModifierRemappings[i].flag) { |
303 case ui::EF_COMMAND_DOWN: | 335 case ui::EF_COMMAND_DOWN: |
304 // Rewrite Command key presses on an Apple keyboard to Control. | 336 // Rewrite Command key presses on an Apple keyboard to Control. |
305 if (IsAppleKeyboard()) { | 337 if (IsAppleKeyboard()) { |
306 DCHECK_EQ(ui::EF_CONTROL_DOWN, kModifierRemappingCtrl->flag); | 338 DCHECK_EQ(ui::EF_CONTROL_DOWN, kModifierRemappingCtrl->flag); |
307 remapped_key = kModifierRemappingCtrl; | 339 remapped_key = kModifierRemappingCtrl; |
308 } | 340 } |
309 break; | 341 break; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 remapped_state->key_code = map.output_key_code; | 379 remapped_state->key_code = map.output_key_code; |
348 remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags; | 380 remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags; |
349 return true; | 381 return true; |
350 } | 382 } |
351 return false; | 383 return false; |
352 } | 384 } |
353 | 385 |
354 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( | 386 ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( |
355 const ui::KeyEvent& key_event, | 387 const ui::KeyEvent& key_event, |
356 scoped_ptr<ui::Event>* rewritten_event) { | 388 scoped_ptr<ui::Event>* rewritten_event) { |
| 389 if (key_event.source_device_id() != ui::ED_UNKNOWN_DEVICE) |
| 390 DeviceKeyPressedOrReleased(key_event.source_device_id()); |
357 MutableKeyState state = {key_event.flags(), key_event.key_code()}; | 391 MutableKeyState state = {key_event.flags(), key_event.key_code()}; |
358 bool is_send_event = IsSendEvent(key_event); | 392 bool is_send_event = IsSendEvent(key_event); |
359 if (!is_send_event) { | 393 if (!is_send_event) { |
360 RewriteModifierKeys(key_event, &state); | 394 RewriteModifierKeys(key_event, &state); |
361 RewriteNumPadKeys(key_event, &state); | 395 RewriteNumPadKeys(key_event, &state); |
362 } | 396 } |
363 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; | 397 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; |
364 if (sticky_keys_controller_) { | 398 if (sticky_keys_controller_) { |
365 status = sticky_keys_controller_->RewriteKeyEvent( | 399 status = sticky_keys_controller_->RewriteKeyEvent( |
366 key_event, state.key_code, &state.flags); | 400 key_event, state.key_code, &state.flags); |
367 if (status == ui::EVENT_REWRITE_DISCARD) | 401 if (status == ui::EVENT_REWRITE_DISCARD) |
368 return ui::EVENT_REWRITE_DISCARD; | 402 return ui::EVENT_REWRITE_DISCARD; |
369 } | 403 } |
370 if (!is_send_event) { | 404 if (!is_send_event) { |
371 RewriteExtendedKeys(key_event, &state); | 405 RewriteExtendedKeys(key_event, &state); |
372 RewriteFunctionKeys(key_event, &state); | 406 RewriteFunctionKeys(key_event, &state); |
373 } | 407 } |
374 if ((key_event.flags() == state.flags) && | 408 if ((key_event.flags() == state.flags) && |
375 (key_event.key_code() == state.key_code) && | 409 (key_event.key_code() == state.key_code) && |
| 410 #if defined(USE_X11) |
| 411 // TODO(kpschoedel): This test is present because several consumers of |
| 412 // key events depend on having a native core X11 event, so we rewrite |
| 413 // all XI2 key events (GenericEvent) into corresponding core X11 key |
| 414 // events. Remove this when event consumers no longer care about |
| 415 // native X11 event details (crbug.com/380349). |
| 416 (!key_event.HasNativeEvent() || |
| 417 (key_event.native_event()->type != GenericEvent)) && |
| 418 #endif |
376 (status == ui::EVENT_REWRITE_CONTINUE)) { | 419 (status == ui::EVENT_REWRITE_CONTINUE)) { |
377 return ui::EVENT_REWRITE_CONTINUE; | 420 return ui::EVENT_REWRITE_CONTINUE; |
378 } | 421 } |
379 // Sticky keys may have returned a result other than |EVENT_REWRITE_CONTINUE|, | 422 // Sticky keys may have returned a result other than |EVENT_REWRITE_CONTINUE|, |
380 // in which case we need to preserve that return status. Alternatively, we | 423 // in which case we need to preserve that return status. Alternatively, we |
381 // might be here because key_event changed, in which case we need to return | 424 // might be here because key_event changed, in which case we need to |
382 // |EVENT_REWRITE_REWRITTEN|. | 425 // return |EVENT_REWRITE_REWRITTEN|. |
383 if (status == ui::EVENT_REWRITE_CONTINUE) | 426 if (status == ui::EVENT_REWRITE_CONTINUE) |
384 status = ui::EVENT_REWRITE_REWRITTEN; | 427 status = ui::EVENT_REWRITE_REWRITTEN; |
385 ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event); | 428 BuildRewrittenKeyEvent( |
386 rewritten_event->reset(rewritten_key_event); | 429 key_event, state.key_code, state.flags, rewritten_event); |
387 rewritten_key_event->set_flags(state.flags); | |
388 rewritten_key_event->set_key_code(state.key_code); | |
389 rewritten_key_event->set_character( | |
390 ui::GetCharacterFromKeyCode(state.key_code, state.flags)); | |
391 rewritten_key_event->NormalizeFlags(); | |
392 #if defined(USE_X11) | |
393 XEvent* xev = rewritten_key_event->native_event(); | |
394 if (xev) { | |
395 CHECK(xev->type == KeyPress || xev->type == KeyRelease); | |
396 XKeyEvent* xkey = &(xev->xkey); | |
397 UpdateX11EventMask(rewritten_key_event->flags(), &xkey->state); | |
398 xkey->keycode = | |
399 XKeysymToKeycode(gfx::GetXDisplay(), | |
400 ui::XKeysymForWindowsKeyCode( | |
401 state.key_code, state.flags & ui::EF_SHIFT_DOWN)); | |
402 } | |
403 #endif | |
404 return status; | 430 return status; |
405 } | 431 } |
406 | 432 |
407 ui::EventRewriteStatus EventRewriter::RewriteMouseButtonEvent( | 433 ui::EventRewriteStatus EventRewriter::RewriteMouseButtonEvent( |
408 const ui::MouseEvent& mouse_event, | 434 const ui::MouseEvent& mouse_event, |
409 scoped_ptr<ui::Event>* rewritten_event) { | 435 scoped_ptr<ui::Event>* rewritten_event) { |
410 int flags = mouse_event.flags(); | 436 int flags = mouse_event.flags(); |
411 RewriteLocatedEvent(mouse_event, &flags); | 437 RewriteLocatedEvent(mouse_event, &flags); |
412 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; | 438 ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; |
413 if (sticky_keys_controller_) | 439 if (sticky_keys_controller_) |
414 status = sticky_keys_controller_->RewriteMouseEvent(mouse_event, &flags); | 440 status = sticky_keys_controller_->RewriteMouseEvent(mouse_event, &flags); |
| 441 int changed_button = ui::EF_NONE; |
| 442 if ((mouse_event.type() == ui::ET_MOUSE_PRESSED) || |
| 443 (mouse_event.type() == ui::ET_MOUSE_RELEASED)) { |
| 444 changed_button = RewriteModifierClick(mouse_event, &flags); |
| 445 } |
415 if ((mouse_event.flags() == flags) && | 446 if ((mouse_event.flags() == flags) && |
416 (status == ui::EVENT_REWRITE_CONTINUE)) { | 447 (status == ui::EVENT_REWRITE_CONTINUE)) { |
417 return ui::EVENT_REWRITE_CONTINUE; | 448 return ui::EVENT_REWRITE_CONTINUE; |
418 } | 449 } |
419 if (status == ui::EVENT_REWRITE_CONTINUE) | 450 if (status == ui::EVENT_REWRITE_CONTINUE) |
420 status = ui::EVENT_REWRITE_REWRITTEN; | 451 status = ui::EVENT_REWRITE_REWRITTEN; |
421 ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event); | 452 ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event); |
422 rewritten_event->reset(rewritten_mouse_event); | 453 rewritten_event->reset(rewritten_mouse_event); |
423 rewritten_mouse_event->set_flags(flags); | 454 rewritten_mouse_event->set_flags(flags); |
| 455 if (changed_button != ui::EF_NONE) |
| 456 rewritten_mouse_event->set_changed_button_flags(changed_button); |
424 #if defined(USE_X11) | 457 #if defined(USE_X11) |
425 XEvent* xev = rewritten_mouse_event->native_event(); | 458 XEvent* xev = rewritten_mouse_event->native_event(); |
426 if (xev) { | 459 if (xev) { |
427 switch (xev->type) { | 460 switch (xev->type) { |
428 case ButtonPress: | 461 case ButtonPress: |
429 case ButtonRelease: { | 462 case ButtonRelease: { |
430 XButtonEvent* xbutton = &(xev->xbutton); | 463 XButtonEvent* xbutton = &(xev->xbutton); |
431 UpdateX11EventMask(rewritten_mouse_event->flags(), &xbutton->state); | 464 UpdateX11EventMask(rewritten_mouse_event->flags(), &xbutton->state); |
| 465 if (changed_button) |
| 466 UpdateX11Button(changed_button, &xbutton->button); |
432 break; | 467 break; |
433 } | 468 } |
434 case GenericEvent: { | 469 case GenericEvent: { |
435 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 470 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
436 CHECK(xievent->evtype == XI_ButtonPress || | 471 CHECK(xievent->evtype == XI_ButtonPress || |
437 xievent->evtype == XI_ButtonRelease); | 472 xievent->evtype == XI_ButtonRelease); |
438 UpdateX11EventMask( | 473 UpdateX11EventMask( |
439 rewritten_mouse_event->flags(), | 474 rewritten_mouse_event->flags(), |
440 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); | 475 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
| 476 if (changed_button) { |
| 477 UpdateX11Button(changed_button, |
| 478 reinterpret_cast<unsigned int*>(&xievent->detail)); |
| 479 } |
441 break; | 480 break; |
442 } | 481 } |
443 default: | 482 default: |
444 NOTREACHED(); | 483 NOTREACHED(); |
445 } | 484 } |
446 } | 485 } |
447 #endif | 486 #endif |
448 return status; | 487 return status; |
449 } | 488 } |
450 | 489 |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 rewritten = RewriteWithKeyboardRemappingsByKeyCode( | 868 rewritten = RewriteWithKeyboardRemappingsByKeyCode( |
830 kNumberKeysToFkeys, arraysize(kNumberKeysToFkeys), incoming, state); | 869 kNumberKeysToFkeys, arraysize(kNumberKeysToFkeys), incoming, state); |
831 } | 870 } |
832 } | 871 } |
833 | 872 |
834 void EventRewriter::RewriteLocatedEvent(const ui::Event& event, | 873 void EventRewriter::RewriteLocatedEvent(const ui::Event& event, |
835 int* flags) { | 874 int* flags) { |
836 const PrefService* pref_service = GetPrefService(); | 875 const PrefService* pref_service = GetPrefService(); |
837 if (!pref_service) | 876 if (!pref_service) |
838 return; | 877 return; |
839 | |
840 // First, remap modifier masks. | |
841 *flags = GetRemappedModifierMasks(*pref_service, event, *flags); | 878 *flags = GetRemappedModifierMasks(*pref_service, event, *flags); |
842 | |
843 #if defined(USE_X11) | |
844 // TODO(kpschoedel): de-X11 with unified device ids from crbug.com/360377 | |
845 XEvent* xevent = event.native_event(); | |
846 if (!xevent || xevent->type != GenericEvent) | |
847 return; | |
848 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); | |
849 if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease) | |
850 return; | |
851 UpdateX11EventMask(*flags, | |
852 reinterpret_cast<unsigned int*>(&xievent->mods.effective)); | |
853 | |
854 // Then, remap Alt+Button1 to Button3. | |
855 if ((xievent->evtype == XI_ButtonPress || | |
856 pressed_device_ids_.count(xievent->sourceid)) && | |
857 (xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) { | |
858 *flags &= ~(ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON); | |
859 *flags |= ui::EF_RIGHT_MOUSE_BUTTON; | |
860 xievent->mods.effective &= ~Mod1Mask; | |
861 xievent->detail = Button3; | |
862 if (xievent->evtype == XI_ButtonRelease) { | |
863 // On the release clear the left button from the existing state and the | |
864 // mods, and set the right button. | |
865 XISetMask(xievent->buttons.mask, Button3); | |
866 XIClearMask(xievent->buttons.mask, Button1); | |
867 xievent->mods.effective &= ~Button1Mask; | |
868 pressed_device_ids_.erase(xievent->sourceid); | |
869 } else { | |
870 pressed_device_ids_.insert(xievent->sourceid); | |
871 } | |
872 } | |
873 #endif // defined(USE_X11) | |
874 } | 879 } |
875 | 880 |
876 EventRewriter::DeviceType EventRewriter::DeviceAddedInternal( | 881 int EventRewriter::RewriteModifierClick(const ui::MouseEvent& mouse_event, |
| 882 int* flags) { |
| 883 // Remap Alt+Button1 to Button3. |
| 884 const int kAltLeftButton = (ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON); |
| 885 if (((*flags & kAltLeftButton) == kAltLeftButton) && |
| 886 ((mouse_event.type() == ui::ET_MOUSE_PRESSED) || |
| 887 pressed_device_ids_.count(mouse_event.source_device_id()))) { |
| 888 *flags &= ~kAltLeftButton; |
| 889 *flags |= ui::EF_RIGHT_MOUSE_BUTTON; |
| 890 if (mouse_event.type() == ui::ET_MOUSE_PRESSED) |
| 891 pressed_device_ids_.insert(mouse_event.source_device_id()); |
| 892 else |
| 893 pressed_device_ids_.erase(mouse_event.source_device_id()); |
| 894 return ui::EF_RIGHT_MOUSE_BUTTON; |
| 895 } |
| 896 return ui::EF_NONE; |
| 897 } |
| 898 |
| 899 EventRewriter::DeviceType EventRewriter::KeyboardDeviceAddedInternal( |
877 int device_id, | 900 int device_id, |
878 const std::string& device_name) { | 901 const std::string& device_name) { |
879 const DeviceType type = GetDeviceType(device_name); | 902 const DeviceType type = GetDeviceType(device_name); |
880 if (type == kDeviceAppleKeyboard) { | 903 if (type == kDeviceAppleKeyboard) { |
881 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " | 904 VLOG(1) << "Apple keyboard '" << device_name << "' connected: " |
882 << "id=" << device_id; | 905 << "id=" << device_id; |
883 } | 906 } |
884 // Always overwrite the existing device_id since the X server may reuse a | 907 // Always overwrite the existing device_id since the X server may reuse a |
885 // device id for an unattached device. | 908 // device id for an unattached device. |
886 device_id_to_type_[device_id] = type; | 909 device_id_to_type_[device_id] = type; |
887 return type; | 910 return type; |
888 } | 911 } |
889 | 912 |
| 913 void EventRewriter::KeyboardDeviceAdded(int device_id) { |
890 #if defined(USE_X11) | 914 #if defined(USE_X11) |
891 void EventRewriter::WillProcessEvent(const ui::PlatformEvent& event) { | |
892 XEvent* xevent = event; | |
893 if (xevent->type == GenericEvent) { | |
894 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); | |
895 if (xievent->evtype == XI_KeyPress || xievent->evtype == XI_KeyRelease) { | |
896 if (xievent->deviceid == xievent->sourceid) | |
897 DeviceKeyPressedOrReleased(xievent->deviceid); | |
898 } | |
899 } | |
900 } | |
901 | |
902 void EventRewriter::DidProcessEvent(const ui::PlatformEvent& event) { | |
903 } | |
904 | |
905 void EventRewriter::DeviceHierarchyChanged() { | |
906 } | |
907 | |
908 void EventRewriter::DeviceAdded(int device_id) { | |
909 DCHECK_NE(XIAllDevices, device_id); | 915 DCHECK_NE(XIAllDevices, device_id); |
910 DCHECK_NE(XIAllMasterDevices, device_id); | 916 DCHECK_NE(XIAllMasterDevices, device_id); |
911 if (device_id == XIAllDevices || device_id == XIAllMasterDevices) { | 917 if (device_id == XIAllDevices || device_id == XIAllMasterDevices) { |
912 LOG(ERROR) << "Unexpected device_id passed: " << device_id; | 918 LOG(ERROR) << "Unexpected device_id passed: " << device_id; |
913 return; | 919 return; |
914 } | 920 } |
915 | 921 |
916 int ndevices_return = 0; | 922 int ndevices_return = 0; |
917 XIDeviceInfo* device_info = | 923 XIDeviceInfo* device_info = |
918 XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return); | 924 XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return); |
919 | 925 |
920 // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices, | 926 // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices, |
921 // the number of devices found should be either 0 (not found) or 1. | 927 // the number of devices found should be either 0 (not found) or 1. |
922 if (!device_info) { | 928 if (!device_info) { |
923 LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown."; | 929 LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown."; |
924 return; | 930 return; |
925 } | 931 } |
926 | 932 |
927 DCHECK_EQ(1, ndevices_return); | 933 DCHECK_EQ(1, ndevices_return); |
928 for (int i = 0; i < ndevices_return; ++i) { | 934 for (int i = 0; i < ndevices_return; ++i) { |
929 DCHECK_EQ(device_id, device_info[i].deviceid); // see the comment above. | 935 DCHECK_EQ(device_id, device_info[i].deviceid); // see the comment above. |
930 DCHECK(device_info[i].name); | 936 DCHECK(device_info[i].name); |
931 DeviceAddedInternal(device_info[i].deviceid, device_info[i].name); | 937 KeyboardDeviceAddedInternal(device_info[i].deviceid, device_info[i].name); |
932 } | 938 } |
933 | 939 |
934 XIFreeDeviceInfo(device_info); | 940 XIFreeDeviceInfo(device_info); |
| 941 #else |
| 942 KeyboardDeviceAddedInternal(device_id, "keyboard"); |
| 943 #endif |
935 } | 944 } |
936 | 945 |
937 void EventRewriter::DeviceRemoved(int device_id) { | |
938 device_id_to_type_.erase(device_id); | |
939 } | |
940 #endif | |
941 | |
942 } // namespace chromeos | 946 } // namespace chromeos |
OLD | NEW |