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

Unified Diff: chrome/browser/chromeos/events/event_rewriter.cc

Issue 248343002: Convert chromeos::EventRewriter to a ui::EventRewriter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@x354034-kder
Patch Set: Bug fix: non-native event under X11 Created 6 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/events/event_rewriter.cc
diff --git a/chrome/browser/chromeos/events/event_rewriter.cc b/chrome/browser/chromeos/events/event_rewriter.cc
index 75e86637fe115839d249d26e928f85961da40f73..06aff53858a9ba5c7f2ebbc12fb80a0e17810640 100644
--- a/chrome/browser/chromeos/events/event_rewriter.cc
+++ b/chrome/browser/chromeos/events/event_rewriter.cc
@@ -4,14 +4,6 @@
#include "chrome/browser/chromeos/events/event_rewriter.h"
-#include <X11/extensions/XInput2.h>
-#include <X11/keysym.h>
-#include <X11/XF86keysym.h>
-#include <X11/Xlib.h>
-// Get rid of macros from Xlib.h that conflicts with other parts of the code.
-#undef RootWindow
-#undef Status
-
#include <vector>
#include "ash/wm/window_state.h"
@@ -21,7 +13,6 @@
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/sys_info.h"
-#include "chrome/browser/chromeos/events/xinput_hierarchy_changed_event_listener.h"
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -29,58 +20,60 @@
#include "chromeos/chromeos_switches.h"
#include "chromeos/ime/ime_keyboard.h"
#include "chromeos/ime/input_method_manager.h"
-#include "ui/base/x/x11_util.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/wm/core/window_util.h"
+#if defined(USE_X11)
+#include <X11/extensions/XInput2.h>
+#include <X11/Xlib.h>
+// Get rid of macros from Xlib.h that conflicts with other parts of the code.
+#undef RootWindow
+#undef Status
+
+#include "chrome/browser/chromeos/events/xinput_hierarchy_changed_event_listener.h"
+#include "ui/base/x/x11_util.h"
+#endif
+
+namespace chromeos {
+
namespace {
const int kBadDeviceId = -1;
-// A key code and a flag we should use when a key is remapped to |remap_to|.
+// Table of key properties of remappable keys and/or remapping targets.
+// This is searched in two distinct ways:
+// - |remap_to| is an |input_method::ModifierKey|, which is the form
+// held in user preferences. |GetRemappedKey()| maps this to the
+// corresponding |key_code| and characterstic event |flag|.
+// - |flag| is a |ui::EventFlags|. |GetRemappedModifierMasks()| maps this
+// to the corresponding user preference |pref_name| for that flag's
+// key, so that it can then be remapped as above.
+// In addition |kModifierRemappingCtrl| is a direct reference to the
+// Control key entry in the table, used in handling Chromebook Diamond
+// and Apple Command keys.
const struct ModifierRemapping {
int remap_to;
int flag;
- unsigned int native_modifier;
- ui::KeyboardCode keycode;
- KeySym native_keysyms[4]; // left, right, shift+left, shift+right.
+ ui::KeyboardCode key_code;
+ const char* pref_name;
} kModifierRemappings[] = {
- { chromeos::input_method::kSearchKey, 0, Mod4Mask, ui::VKEY_LWIN,
- { XK_Super_L, XK_Super_L, XK_Super_L, XK_Super_L }},
- { chromeos::input_method::kControlKey, ui::EF_CONTROL_DOWN, ControlMask,
- ui::VKEY_CONTROL,
- { XK_Control_L, XK_Control_R, XK_Control_L, XK_Control_R }},
- { chromeos::input_method::kAltKey, ui::EF_ALT_DOWN, Mod1Mask,
- ui::VKEY_MENU, { XK_Alt_L, XK_Alt_R, XK_Meta_L, XK_Meta_R }},
- { chromeos::input_method::kVoidKey, 0, 0U, ui::VKEY_UNKNOWN,
- { XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol, XK_VoidSymbol }},
- { chromeos::input_method::kCapsLockKey, 0, 0U, ui::VKEY_CAPITAL,
- { XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock, XK_Caps_Lock }},
- { chromeos::input_method::kEscapeKey, 0, 0U, ui::VKEY_ESCAPE,
- { XK_Escape, XK_Escape, XK_Escape, XK_Escape }},
+ {input_method::kSearchKey, ui::EF_COMMAND_DOWN, ui::VKEY_LWIN,
+ prefs::kLanguageRemapSearchKeyTo},
+ {input_method::kControlKey, ui::EF_CONTROL_DOWN, ui::VKEY_CONTROL,
+ prefs::kLanguageRemapControlKeyTo},
+ {input_method::kAltKey, ui::EF_ALT_DOWN, ui::VKEY_MENU,
+ prefs::kLanguageRemapAltKeyTo},
+ {input_method::kVoidKey, 0, ui::VKEY_UNKNOWN, NULL},
+ {input_method::kCapsLockKey, ui::EF_CAPS_LOCK_DOWN, ui::VKEY_CAPITAL,
+ prefs::kLanguageRemapCapsLockKeyTo},
+ {input_method::kEscapeKey, 0, ui::VKEY_ESCAPE, NULL},
+ {0, 0, ui::VKEY_F15, prefs::kLanguageRemapDiamondKeyTo},
};
const ModifierRemapping* kModifierRemappingCtrl = &kModifierRemappings[1];
-// A structure for converting |native_modifier| to a pair of |flag| and
-// |pref_name|.
-const struct ModifierFlagToPrefName {
- unsigned int native_modifier;
- int flag;
- const char* pref_name;
-} kModifierFlagToPrefName[] = {
- // TODO(yusukes): When the device has a Chrome keyboard (i.e. the one without
- // Caps Lock), we should not check kLanguageRemapCapsLockKeyTo.
- { Mod3Mask, 0, prefs::kLanguageRemapCapsLockKeyTo },
- { Mod4Mask, 0, prefs::kLanguageRemapSearchKeyTo },
- { ControlMask, ui::EF_CONTROL_DOWN, prefs::kLanguageRemapControlKeyTo },
- { Mod1Mask, ui::EF_ALT_DOWN, prefs::kLanguageRemapAltKeyTo },
- { Mod2Mask, 0, prefs::kLanguageRemapDiamondKeyTo },
-};
-
// Gets a remapped key for |pref_name| key. For example, to find out which
// key Search is currently remapped to, call the function with
// prefs::kLanguageRemapSearchKeyTo.
@@ -96,21 +89,6 @@ const ModifierRemapping* GetRemappedKey(const std::string& pref_name,
return NULL;
}
-bool IsRight(KeySym native_keysym) {
- switch (native_keysym) {
- case XK_Alt_R:
- case XK_Control_R:
- case XK_Hyper_R:
- case XK_Meta_R:
- case XK_Shift_R:
- case XK_Super_R:
- return true;
- default:
- break;
- }
- return false;
-}
-
bool HasDiamondKey() {
return CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kHasChromeOSDiamondKey);
@@ -121,31 +99,52 @@ bool IsISOLevel5ShiftUsedByCurrentInputMethod() {
// it's not possible to make both features work. For now, we don't remap
// Mod3Mask when Neo2 is in use.
// TODO(yusukes): Remove the restriction.
- chromeos::input_method::InputMethodManager* manager =
- chromeos::input_method::InputMethodManager::Get();
+ input_method::InputMethodManager* manager =
+ input_method::InputMethodManager::Get();
return manager->IsISOLevel5ShiftUsedByCurrentInputMethod();
}
-} // namespace
+EventRewriter::DeviceType GetDeviceType(const std::string& device_name) {
+ std::vector<std::string> tokens;
+ Tokenize(device_name, " .", &tokens);
-namespace chromeos {
+ // If the |device_name| contains the two words, "apple" and "keyboard", treat
+ // it as an Apple keyboard.
+ bool found_apple = false;
+ bool found_keyboard = false;
+ for (size_t i = 0; i < tokens.size(); ++i) {
+ if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple"))
+ found_apple = true;
+ if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
+ found_keyboard = true;
+ if (found_apple && found_keyboard)
+ return EventRewriter::kDeviceAppleKeyboard;
+ }
+
+ return EventRewriter::kDeviceUnknown;
+}
+
+} // namespace
EventRewriter::EventRewriter()
: last_device_id_(kBadDeviceId),
- keyboard_for_testing_(NULL),
+ ime_keyboard_for_testing_(NULL),
pref_service_for_testing_(NULL) {
+#if defined(USE_X11)
ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
if (base::SysInfo::IsRunningOnChromeOS()) {
XInputHierarchyChangedEventListener::GetInstance()->AddObserver(this);
}
- RefreshKeycodes();
+#endif
}
EventRewriter::~EventRewriter() {
+#if defined(USE_X11)
ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
if (base::SysInfo::IsRunningOnChromeOS()) {
XInputHierarchyChangedEventListener::GetInstance()->RemoveObserver(this);
}
+#endif
}
EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting(
@@ -154,178 +153,84 @@ EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting(
return DeviceAddedInternal(device_id, device_name);
}
-// static
-EventRewriter::DeviceType EventRewriter::GetDeviceType(
- const std::string& device_name) {
- std::vector<std::string> tokens;
- Tokenize(device_name, " .", &tokens);
+void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event,
+ int* flags) {
+ MutableKeyState state = {*flags, ui::VKEY_UNKNOWN};
+ RewriteLocatedEvent(event, &state);
+ *flags = state.flags;
+}
- // If the |device_name| contains the two words, "apple" and "keyboard", treat
- // it as an Apple keyboard.
- bool found_apple = false;
- bool found_keyboard = false;
- for (size_t i = 0; i < tokens.size(); ++i) {
- if (!found_apple && LowerCaseEqualsASCII(tokens[i], "apple"))
- found_apple = true;
- if (!found_keyboard && LowerCaseEqualsASCII(tokens[i], "keyboard"))
- found_keyboard = true;
- if (found_apple && found_keyboard)
- return kDeviceAppleKeyboard;
+ui::EventRewriteStatus EventRewriter::RewriteEvent(
+ const ui::Event& event,
+ scoped_ptr<ui::Event>* rewritten_event) {
+#if defined(USE_X11)
+ // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
+ // crbug.com/136465.
+ XEvent* xev = event.native_event();
+ if (xev && xev->xany.send_event)
+ return ui::EVENT_REWRITE_CONTINUE;
+#endif
+ switch (event.type()) {
+ case ui::ET_KEY_PRESSED:
+ case ui::ET_KEY_RELEASED: {
+ const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event);
+ MutableKeyState state = {key_event.flags(), key_event.key_code()};
+ RewriteModifierKeys(key_event, &state);
+ RewriteNumPadKeys(key_event, &state);
+ RewriteExtendedKeys(key_event, &state);
+ RewriteFunctionKeys(key_event, &state);
+ if ((key_event.flags() != state.flags) ||
+ (key_event.key_code() != state.key_code)) {
+ ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event);
+ rewritten_event->reset(rewritten_key_event);
+ rewritten_key_event->set_flags(state.flags);
+ rewritten_key_event->set_key_code(state.key_code);
+ return ui::EVENT_REWRITE_REWRITTEN;
+ }
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+ case ui::ET_MOUSE_PRESSED:
+ case ui::ET_MOUSE_RELEASED:
+ case ui::ET_TOUCH_PRESSED:
+ case ui::ET_TOUCH_RELEASED: {
+ MutableKeyState state = {event.flags(), ui::VKEY_UNKNOWN};
+ RewriteLocatedEvent(event, &state);
+ if (event.flags() != state.flags) {
+ if (event.IsMouseEvent()) {
+ rewritten_event->reset(
+ new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event)));
+ } else {
+ rewritten_event->reset(
+ new ui::TouchEvent(static_cast<const ui::TouchEvent&>(event)));
+ }
+ rewritten_event->get()->set_flags(state.flags);
+ return ui::EVENT_REWRITE_REWRITTEN;
+ }
+ return ui::EVENT_REWRITE_CONTINUE;
+ }
+ default:
+ return ui::EVENT_REWRITE_CONTINUE;
}
-
- return kDeviceUnknown;
+ NOTREACHED();
}
-void EventRewriter::RewriteForTesting(XEvent* event) {
- Rewrite(event);
+ui::EventRewriteStatus EventRewriter::NextDispatchEvent(
+ const ui::Event& last_event,
+ scoped_ptr<ui::Event>* new_event) {
+ NOTREACHED();
+ return ui::EVENT_REWRITE_CONTINUE;
}
+#if defined(USE_X11)
void EventRewriter::DeviceKeyPressedOrReleased(int device_id) {
- std::map<int, DeviceType>::const_iterator iter =
- device_id_to_type_.find(device_id);
- if (iter == device_id_to_type_.end()) {
+ if (!device_id_to_type_.count(device_id)) {
// |device_id| is unknown. This means the device was connected before
// booting the OS. Query the name of the device and add it to the map.
DeviceAdded(device_id);
}
-
last_device_id_ = device_id;
}
-
-void EventRewriter::WillProcessEvent(const ui::PlatformEvent& event) {
- XEvent* xevent = event;
- if (xevent->type == KeyPress || xevent->type == KeyRelease) {
- Rewrite(xevent);
- } else if (xevent->type == GenericEvent) {
- XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
- if (xievent->evtype == XI_KeyPress || xievent->evtype == XI_KeyRelease) {
- if (xievent->deviceid == xievent->sourceid)
- DeviceKeyPressedOrReleased(xievent->deviceid);
- } else {
- RewriteLocatedEvent(xevent);
- }
- } else if (xevent->type == MappingNotify) {
- if (xevent->xmapping.request == MappingModifier ||
- xevent->xmapping.request == MappingKeyboard) {
- RefreshKeycodes();
- }
- }
-}
-
-void EventRewriter::DidProcessEvent(const ui::PlatformEvent& event) {
-}
-
-void EventRewriter::DeviceHierarchyChanged() {}
-
-void EventRewriter::DeviceAdded(int device_id) {
- DCHECK_NE(XIAllDevices, device_id);
- DCHECK_NE(XIAllMasterDevices, device_id);
- if (device_id == XIAllDevices || device_id == XIAllMasterDevices) {
- LOG(ERROR) << "Unexpected device_id passed: " << device_id;
- return;
- }
-
- int ndevices_return = 0;
- XIDeviceInfo* device_info = XIQueryDevice(gfx::GetXDisplay(),
- device_id,
- &ndevices_return);
-
- // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices,
- // the number of devices found should be either 0 (not found) or 1.
- if (!device_info) {
- LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown.";
- return;
- }
-
- DCHECK_EQ(1, ndevices_return);
- for (int i = 0; i < ndevices_return; ++i) {
- DCHECK_EQ(device_id, device_info[i].deviceid); // see the comment above.
- DCHECK(device_info[i].name);
- DeviceAddedInternal(device_info[i].deviceid, device_info[i].name);
- }
-
- XIFreeDeviceInfo(device_info);
-}
-
-void EventRewriter::DeviceRemoved(int device_id) {
- device_id_to_type_.erase(device_id);
-}
-
-void EventRewriter::RefreshKeycodes() {
- keysym_to_keycode_map_.clear();
-}
-
-KeyCode EventRewriter::NativeKeySymToNativeKeycode(KeySym keysym) {
- if (keysym_to_keycode_map_.count(keysym))
- return keysym_to_keycode_map_[keysym];
-
- XDisplay* display = gfx::GetXDisplay();
- KeyCode keycode = XKeysymToKeycode(display, keysym);
- keysym_to_keycode_map_[keysym] = keycode;
- return keycode;
-}
-
-bool EventRewriter::TopRowKeysAreFunctionKeys(XEvent* event) const {
- const PrefService* prefs = GetPrefService();
- if (prefs &&
- prefs->FindPreference(prefs::kLanguageSendFunctionKeys) &&
- prefs->GetBoolean(prefs::kLanguageSendFunctionKeys))
- return true;
-
- ash::wm::WindowState* state = ash::wm::GetActiveWindowState();
- return state ? state->top_row_keys_are_function_keys() : false;
-}
-
-bool EventRewriter::RewriteWithKeyboardRemappingsByKeySym(
- const KeyboardRemapping* remappings,
- size_t num_remappings,
- KeySym keysym,
- unsigned int native_mods,
- KeySym* remapped_native_keysym,
- unsigned int* remapped_native_mods) {
- for (size_t i = 0; i < num_remappings; ++i) {
- const KeyboardRemapping& map = remappings[i];
-
- if (keysym != map.input_keysym)
- continue;
- unsigned int matched_mods = native_mods & map.input_native_mods;
- if (matched_mods != map.input_native_mods)
- continue;
-
- *remapped_native_keysym = map.output_keysym;
- *remapped_native_mods = (native_mods & ~map.input_native_mods) |
- map.output_native_mods;
- return true;
- }
-
- return false;
-}
-
-bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode(
- const KeyboardRemapping* remappings,
- size_t num_remappings,
- KeyCode keycode,
- unsigned int native_mods,
- KeySym* remapped_native_keysym,
- unsigned int* remapped_native_mods) {
- for (size_t i = 0; i < num_remappings; ++i) {
- const KeyboardRemapping& map = remappings[i];
-
- KeyCode input_keycode = NativeKeySymToNativeKeycode(map.input_keysym);
- if (keycode != input_keycode)
- continue;
- unsigned int matched_mods = native_mods & map.input_native_mods;
- if (matched_mods != map.input_native_mods)
- continue;
-
- *remapped_native_keysym = map.output_keysym;
- *remapped_native_mods = (native_mods & ~map.input_native_mods) |
- map.output_native_mods;
- return true;
- }
-
- return false;
-}
+#endif
const PrefService* EventRewriter::GetPrefService() const {
if (pref_service_for_testing_)
@@ -334,18 +239,6 @@ const PrefService* EventRewriter::GetPrefService() const {
return profile ? profile->GetPrefs() : NULL;
}
-void EventRewriter::Rewrite(XEvent* event) {
- // Do not rewrite an event sent by ui_controls::SendKeyPress(). See
- // crbug.com/136465.
- if (event->xkey.send_event)
- return;
-
- RewriteModifiers(event);
- RewriteNumPadKeys(event);
- RewriteExtendedKeys(event);
- RewriteFunctionKeys(event);
-}
-
bool EventRewriter::IsAppleKeyboard() const {
if (last_device_id_ == kBadDeviceId)
return false;
@@ -362,63 +255,78 @@ bool EventRewriter::IsAppleKeyboard() const {
return type == kDeviceAppleKeyboard;
}
-void EventRewriter::GetRemappedModifierMasks(
- unsigned int original_native_modifiers,
- unsigned int* remapped_native_modifiers) const {
- // TODO(glotov): remove the following condition when we do not restart chrome
- // when user logs in as guest. See Rewrite() for details.
- if (UserManager::Get()->IsLoggedInAsGuest() &&
- LoginDisplayHostImpl::default_host()) {
- return;
- }
+bool EventRewriter::TopRowKeysAreFunctionKeys(const ui::KeyEvent& event) const {
+ const PrefService* prefs = GetPrefService();
+ if (prefs && prefs->FindPreference(prefs::kLanguageSendFunctionKeys) &&
+ prefs->GetBoolean(prefs::kLanguageSendFunctionKeys))
+ return true;
- const PrefService* pref_service = GetPrefService();
- if (!pref_service)
- return;
+ ash::wm::WindowState* state = ash::wm::GetActiveWindowState();
+ return state ? state->top_row_keys_are_function_keys() : false;
+}
- // When a diamond key is not available, a Mod2Mask should not treated as a
- // configurable modifier because Mod2Mask may be worked as NumLock mask.
- // (cf. http://crbug.com/173956)
- const bool skip_mod2 = !HasDiamondKey();
- // If Mod3 is used by the current input method, don't allow the CapsLock
- // pref to remap it, or the keyboard behavior will be broken.
- const bool skip_mod3 = IsISOLevel5ShiftUsedByCurrentInputMethod();
-
- for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) {
- if ((skip_mod2 && kModifierFlagToPrefName[i].native_modifier == Mod2Mask) ||
- (skip_mod3 && kModifierFlagToPrefName[i].native_modifier == Mod3Mask)) {
+int EventRewriter::GetRemappedModifierMasks(const PrefService& pref_service,
+ const ui::Event& event,
+ int original_flags) const {
+ int unmodified_flags = original_flags;
+ int rewritten_flags = 0;
+ for (size_t i = 0; unmodified_flags && (i < arraysize(kModifierRemappings));
+ ++i) {
+ const ModifierRemapping* remapped_key = 0;
+ if (!(unmodified_flags & kModifierRemappings[i].flag))
continue;
+ switch (kModifierRemappings[i].flag) {
+ case ui::EF_COMMAND_DOWN:
+ // Rewrite Command key presses on an Apple keyboard to Control.
+ if (IsAppleKeyboard()) {
+ DCHECK_EQ(ui::EF_CONTROL_DOWN, kModifierRemappingCtrl->flag);
+ remapped_key = kModifierRemappingCtrl;
+ }
+ break;
+ case ui::EF_CAPS_LOCK_DOWN:
+ // If CapsLock is used by the current input method, don't allow the
+ // CapsLock pref to remap it, or the keyboard behavior will be broken.
+ if (IsISOLevel5ShiftUsedByCurrentInputMethod())
+ continue;
+ break;
+ default:
+ break;
}
- if (original_native_modifiers &
- kModifierFlagToPrefName[i].native_modifier) {
- const ModifierRemapping* remapped_key =
- GetRemappedKey(kModifierFlagToPrefName[i].pref_name, *pref_service);
- // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
- if (IsAppleKeyboard() &&
- (kModifierFlagToPrefName[i].native_modifier == Mod4Mask)) {
- remapped_key = kModifierRemappingCtrl;
- }
- if (remapped_key) {
- *remapped_native_modifiers |= remapped_key->native_modifier;
- } else {
- *remapped_native_modifiers |=
- kModifierFlagToPrefName[i].native_modifier;
- }
+ if (!remapped_key && kModifierRemappings[i].pref_name) {
+ remapped_key =
+ GetRemappedKey(kModifierRemappings[i].pref_name, pref_service);
+ }
+ if (remapped_key) {
+ unmodified_flags &= ~kModifierRemappings[i].flag;
+ rewritten_flags |= remapped_key->flag;
}
}
+ return rewritten_flags | unmodified_flags;
+}
- unsigned int native_mask = Mod4Mask | ControlMask | Mod1Mask;
- if (!skip_mod2)
- native_mask |= Mod2Mask;
- if (!skip_mod3)
- native_mask |= Mod3Mask;
- *remapped_native_modifiers =
- (original_native_modifiers & ~native_mask) |
- *remapped_native_modifiers;
+bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode(
+ const KeyboardRemapping* remappings,
+ size_t num_remappings,
+ const MutableKeyState& input,
+ MutableKeyState* remapped_state) {
+ for (size_t i = 0; i < num_remappings; ++i) {
+ const KeyboardRemapping& map = remappings[i];
+ if (input.key_code != map.input_key_code)
+ continue;
+ if ((input.flags & map.input_flags) != map.input_flags)
+ continue;
+ remapped_state->key_code = map.output_key_code;
+ remapped_state->flags = (input.flags & ~map.input_flags) | map.output_flags;
+ return true;
+ }
+ return false;
}
-bool EventRewriter::RewriteModifiers(XEvent* event) {
- DCHECK(event->type == KeyPress || event->type == KeyRelease);
+void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event,
+ MutableKeyState* state) {
+ DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
+ key_event.type() == ui::ET_KEY_RELEASED);
+
// Do nothing if we have just logged in as guest but have not restarted chrome
// process yet (so we are still on the login screen). In this situations we
// have no user profile so can not do anything useful.
@@ -426,28 +334,25 @@ bool EventRewriter::RewriteModifiers(XEvent* event) {
// restart chrome process. In future this is to be changed.
// TODO(glotov): remove the following condition when we do not restart chrome
// when user logs in as guest.
+ // TODO(kpschoedel): check whether this is still necessary.
if (UserManager::Get()->IsLoggedInAsGuest() &&
LoginDisplayHostImpl::default_host())
- return false;
+ return;
const PrefService* pref_service = GetPrefService();
if (!pref_service)
- return false;
-
- DCHECK_EQ(input_method::kControlKey, kModifierRemappingCtrl->remap_to);
+ return;
- XKeyEvent* xkey = &event->xkey;
- KeySym keysym = XLookupKeysym(xkey, 0);
- ui::KeyboardCode original_keycode = ui::KeyboardCodeFromNative(event);
- ui::KeyboardCode remapped_keycode = original_keycode;
- KeyCode remapped_native_keycode = xkey->keycode;
+ MutableKeyState incoming = *state;
+ state->flags = ui::EF_NONE;
+ int characteristic_flag = ui::EF_NONE;
- // First, remap |keysym|.
+ // First, remap the key code.
const ModifierRemapping* remapped_key = NULL;
- switch (keysym) {
- // On Chrome OS, XF86XK_Launch6 (F15) with Mod2Mask is sent when Diamond
- // key is pressed.
- case XF86XK_Launch6:
+ switch (incoming.key_code) {
+ // On Chrome OS, F15 (XF86XK_Launch6) with NumLock (Mod2Mask) is sent
+ // when Diamond key is pressed.
+ case ui::VKEY_F15:
// When diamond key is not available, the configuration UI for Diamond
// key is not shown. Therefore, ignore the kLanguageRemapDiamondKeyTo
// syncable pref.
@@ -455,37 +360,43 @@ bool EventRewriter::RewriteModifiers(XEvent* event) {
remapped_key =
GetRemappedKey(prefs::kLanguageRemapDiamondKeyTo, *pref_service);
// Default behavior is Ctrl key.
- if (!remapped_key)
+ if (!remapped_key) {
+ DCHECK_EQ(ui::VKEY_CONTROL, kModifierRemappingCtrl->key_code);
remapped_key = kModifierRemappingCtrl;
+ characteristic_flag = ui::EF_CONTROL_DOWN;
+ }
break;
// On Chrome OS, XF86XK_Launch7 (F16) with Mod3Mask is sent when Caps Lock
// is pressed (with one exception: when
// IsISOLevel5ShiftUsedByCurrentInputMethod() is true, the key generates
// XK_ISO_Level3_Shift with Mod3Mask, not XF86XK_Launch7).
- case XF86XK_Launch7:
+ case ui::VKEY_F16:
+ characteristic_flag = ui::EF_CAPS_LOCK_DOWN;
remapped_key =
GetRemappedKey(prefs::kLanguageRemapCapsLockKeyTo, *pref_service);
break;
- case XK_Super_L:
- case XK_Super_R:
- // Rewrite Command-L/R key presses on an Apple keyboard to Control-L/R.
- if (IsAppleKeyboard())
+ case ui::VKEY_LWIN:
+ case ui::VKEY_RWIN:
+ characteristic_flag = ui::EF_COMMAND_DOWN;
+ // Rewrite Command-L/R key presses on an Apple keyboard to Control.
+ if (IsAppleKeyboard()) {
+ DCHECK_EQ(ui::VKEY_CONTROL, kModifierRemappingCtrl->key_code);
remapped_key = kModifierRemappingCtrl;
- else
+ } else {
remapped_key =
GetRemappedKey(prefs::kLanguageRemapSearchKeyTo, *pref_service);
+ }
// Default behavior is Super key, hence don't remap the event if the pref
// is unavailable.
break;
- case XK_Control_L:
- case XK_Control_R:
+ case ui::VKEY_CONTROL:
+ characteristic_flag = ui::EF_CONTROL_DOWN;
remapped_key =
GetRemappedKey(prefs::kLanguageRemapControlKeyTo, *pref_service);
break;
- case XK_Alt_L:
- case XK_Alt_R:
- case XK_Meta_L:
- case XK_Meta_R:
+ case ui::VKEY_MENU:
+ // ALT key
+ characteristic_flag = ui::EF_ALT_DOWN;
remapped_key =
GetRemappedKey(prefs::kLanguageRemapAltKeyTo, *pref_service);
break;
@@ -494,308 +405,186 @@ bool EventRewriter::RewriteModifiers(XEvent* event) {
}
if (remapped_key) {
- int flags = ui::EventFlagsFromNative(event);
- remapped_keycode = remapped_key->keycode;
- const size_t level = ((flags & ui::EF_SHIFT_DOWN) ? (1 << 1) : 0) +
- (IsRight(keysym) ? (1 << 0) : 0);
- const KeySym native_keysym = remapped_key->native_keysyms[level];
- remapped_native_keycode = NativeKeySymToNativeKeycode(native_keysym);
+ state->key_code = remapped_key->key_code;
+ incoming.flags |= characteristic_flag;
+ characteristic_flag = remapped_key->flag;
}
// Next, remap modifier bits.
- unsigned int remapped_native_modifiers = 0U;
- GetRemappedModifierMasks(xkey->state, &remapped_native_modifiers);
+ state->flags |=
+ GetRemappedModifierMasks(*pref_service, key_event, incoming.flags);
+ if (key_event.type() == ui::ET_KEY_PRESSED)
+ state->flags |= characteristic_flag;
+ else
+ state->flags &= ~characteristic_flag;
// Toggle Caps Lock if the remapped key is ui::VKEY_CAPITAL, but do nothing if
// the original key is ui::VKEY_CAPITAL (i.e. a Caps Lock key on an external
// keyboard is pressed) since X can handle that case.
- if (event->type == KeyPress &&
- original_keycode != ui::VKEY_CAPITAL &&
- remapped_keycode == ui::VKEY_CAPITAL) {
- input_method::ImeKeyboard* keyboard = keyboard_for_testing_ ?
- keyboard_for_testing_ :
- input_method::InputMethodManager::Get()->GetImeKeyboard();
- keyboard->SetCapsLockEnabled(!keyboard->CapsLockIsEnabled());
+ if (key_event.type() == ui::ET_KEY_PRESSED &&
+ incoming.key_code != ui::VKEY_CAPITAL &&
+ state->key_code == ui::VKEY_CAPITAL) {
+ chromeos::input_method::ImeKeyboard* ime_keyboard =
+ ime_keyboard_for_testing_
+ ? ime_keyboard_for_testing_
+ : chromeos::input_method::InputMethodManager::Get()
+ ->GetImeKeyboard();
+ ime_keyboard->SetCapsLockEnabled(!ime_keyboard->CapsLockIsEnabled());
}
-
- OverwriteEvent(event, remapped_native_keycode, remapped_native_modifiers);
- return true;
}
-bool EventRewriter::RewriteNumPadKeys(XEvent* event) {
- DCHECK(event->type == KeyPress || event->type == KeyRelease);
- bool rewritten = false;
- XKeyEvent* xkey = &event->xkey;
- const KeySym keysym = XLookupKeysym(xkey, 0);
- switch (keysym) {
- case XK_KP_Insert:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_0),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Delete:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_Decimal),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_End:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_1),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Down:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_2),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Next:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_3),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Left:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_4),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Begin:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_5),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Right:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_6),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Home:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_7),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Up:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_8),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Prior:
- OverwriteEvent(event, NativeKeySymToNativeKeycode(XK_KP_9),
- xkey->state | Mod2Mask);
- rewritten = true;
- break;
- case XK_KP_Divide:
- case XK_KP_Multiply:
- case XK_KP_Subtract:
- case XK_KP_Add:
- case XK_KP_Enter:
- // Add Mod2Mask for consistency.
- OverwriteEvent(event, xkey->keycode, xkey->state | Mod2Mask);
- rewritten = true;
- break;
- default:
- break;
- }
- return rewritten;
+void EventRewriter::RewriteNumPadKeys(const ui::KeyEvent& key_event,
+ MutableKeyState* state) {
+ DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
+ key_event.type() == ui::ET_KEY_RELEASED);
+ if (!(state->flags & ui::EF_NUMPAD_KEY))
+ return;
+ MutableKeyState incoming = *state;
+
+ static const KeyboardRemapping kNumPadRemappings[] = {
+ {ui::VKEY_INSERT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD0, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_DELETE, ui::EF_NUMPAD_KEY, ui::VKEY_DECIMAL, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_END, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD1, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_DOWN, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD2, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_NEXT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD3, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_LEFT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD4, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_CLEAR, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD5, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_RIGHT, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD6, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_HOME, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD7, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_UP, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD8, ui::EF_NUMPAD_KEY},
+ {ui::VKEY_PRIOR, ui::EF_NUMPAD_KEY, ui::VKEY_NUMPAD9, ui::EF_NUMPAD_KEY},
+ };
+
+ RewriteWithKeyboardRemappingsByKeyCode(
+ kNumPadRemappings, arraysize(kNumPadRemappings), incoming, state);
}
-bool EventRewriter::RewriteExtendedKeys(XEvent* event) {
- DCHECK(event->type == KeyPress || event->type == KeyRelease);
- XKeyEvent* xkey = &event->xkey;
- const KeySym keysym = XLookupKeysym(xkey, 0);
+void EventRewriter::RewriteExtendedKeys(const ui::KeyEvent& key_event,
+ MutableKeyState* state) {
+ DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
+ key_event.type() == ui::ET_KEY_RELEASED);
- KeySym remapped_native_keysym = 0;
- unsigned int remapped_native_mods = 0;
+ MutableKeyState incoming = *state;
bool rewritten = false;
- if (xkey->state & Mod4Mask) {
+ if ((incoming.flags & (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) ==
+ (ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN)) {
// Allow Search to avoid rewriting extended keys.
static const KeyboardRemapping kAvoidRemappings[] = {
- { // Alt+Backspace
- XK_BackSpace, Mod1Mask | Mod4Mask,
- XK_BackSpace, Mod1Mask,
- },
- { // Control+Alt+Up
- XK_Up, Mod1Mask | ControlMask | Mod4Mask,
- XK_Up, Mod1Mask | ControlMask,
- },
- { // Alt+Up
- XK_Up, Mod1Mask | Mod4Mask,
- XK_Up, Mod1Mask,
- },
- { // Control+Alt+Down
- XK_Down, Mod1Mask | ControlMask | Mod4Mask,
- XK_Down, Mod1Mask | ControlMask,
- },
- { // Alt+Down
- XK_Down, Mod1Mask | Mod4Mask,
- XK_Down, Mod1Mask,
- }
- };
-
- rewritten = RewriteWithKeyboardRemappingsByKeySym(
- kAvoidRemappings,
- arraysize(kAvoidRemappings),
- keysym,
- xkey->state,
- &remapped_native_keysym,
- &remapped_native_mods);
+ { // Alt+Backspace
+ ui::VKEY_BACK, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_BACK,
+ ui::EF_ALT_DOWN,
+ },
+ { // Control+Alt+Up
+ ui::VKEY_UP,
+ ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN,
+ ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
+ },
+ { // Alt+Up
+ ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_UP,
+ ui::EF_ALT_DOWN,
+ },
+ { // Control+Alt+Down
+ ui::VKEY_DOWN,
+ ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_COMMAND_DOWN,
+ ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN,
+ },
+ { // Alt+Down
+ ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN, ui::VKEY_DOWN,
+ ui::EF_ALT_DOWN,
+ }};
+
+ rewritten = RewriteWithKeyboardRemappingsByKeyCode(
+ kAvoidRemappings, arraysize(kAvoidRemappings), incoming, state);
}
- if (!rewritten) {
+ if (!rewritten && (incoming.flags & ui::EF_COMMAND_DOWN)) {
static const KeyboardRemapping kSearchRemappings[] = {
- { // Search+BackSpace -> Delete
- XK_BackSpace, Mod4Mask,
- XK_Delete, 0
- },
- { // Search+Left -> Home
- XK_Left, Mod4Mask,
- XK_Home, 0
- },
- { // Search+Up -> Prior (aka PageUp)
- XK_Up, Mod4Mask,
- XK_Prior, 0
- },
- { // Search+Right -> End
- XK_Right, Mod4Mask,
- XK_End, 0
- },
- { // Search+Down -> Next (aka PageDown)
- XK_Down, Mod4Mask,
- XK_Next, 0
- },
- { // Search+Period -> Insert
- XK_period, Mod4Mask,
- XK_Insert, 0
- }
- };
-
- rewritten = RewriteWithKeyboardRemappingsByKeySym(
- kSearchRemappings,
- arraysize(kSearchRemappings),
- keysym,
- xkey->state,
- &remapped_native_keysym,
- &remapped_native_mods);
- }
+ { // Search+BackSpace -> Delete
+ ui::VKEY_BACK, ui::EF_COMMAND_DOWN, ui::VKEY_DELETE, 0},
+ { // Search+Left -> Home
+ ui::VKEY_LEFT, ui::EF_COMMAND_DOWN, ui::VKEY_HOME, 0},
+ { // Search+Up -> Prior (aka PageUp)
+ ui::VKEY_UP, ui::EF_COMMAND_DOWN, ui::VKEY_PRIOR, 0},
+ { // Search+Right -> End
+ ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN, ui::VKEY_END, 0},
+ { // Search+Down -> Next (aka PageDown)
+ ui::VKEY_DOWN, ui::EF_COMMAND_DOWN, ui::VKEY_NEXT, 0},
+ { // Search+Period -> Insert
+ ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN, ui::VKEY_INSERT, 0}};
- if (!rewritten) {
- static const KeyboardRemapping kNonSearchRemappings[] = {
- { // Alt+BackSpace -> Delete
- XK_BackSpace, Mod1Mask,
- XK_Delete, 0
- },
- { // Control+Alt+Up -> Home
- XK_Up, Mod1Mask | ControlMask,
- XK_Home, 0
- },
- { // Alt+Up -> Prior (aka PageUp)
- XK_Up, Mod1Mask,
- XK_Prior, 0
- },
- { // Control+Alt+Down -> End
- XK_Down, Mod1Mask | ControlMask,
- XK_End, 0
- },
- { // Alt+Down -> Next (aka PageDown)
- XK_Down, Mod1Mask,
- XK_Next, 0
- }
- };
-
- rewritten = RewriteWithKeyboardRemappingsByKeySym(
- kNonSearchRemappings,
- arraysize(kNonSearchRemappings),
- keysym,
- xkey->state,
- &remapped_native_keysym,
- &remapped_native_mods);
+ rewritten = RewriteWithKeyboardRemappingsByKeyCode(
+ kSearchRemappings, arraysize(kSearchRemappings), incoming, state);
}
- if (!rewritten)
- return false;
+ if (!rewritten && (incoming.flags & ui::EF_ALT_DOWN)) {
+ static const KeyboardRemapping kNonSearchRemappings[] = {
+ { // Alt+BackSpace -> Delete
+ ui::VKEY_BACK, ui::EF_ALT_DOWN, ui::VKEY_DELETE, 0},
+ { // Control+Alt+Up -> Home
+ ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::VKEY_HOME, 0},
+ { // Alt+Up -> Prior (aka PageUp)
+ ui::VKEY_UP, ui::EF_ALT_DOWN, ui::VKEY_PRIOR, 0},
+ { // Control+Alt+Down -> End
+ ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, ui::VKEY_END, 0},
+ { // Alt+Down -> Next (aka PageDown)
+ ui::VKEY_DOWN, ui::EF_ALT_DOWN, ui::VKEY_NEXT, 0}};
- OverwriteEvent(event,
- NativeKeySymToNativeKeycode(remapped_native_keysym),
- remapped_native_mods);
- return true;
+ rewritten = RewriteWithKeyboardRemappingsByKeyCode(
+ kNonSearchRemappings, arraysize(kNonSearchRemappings), incoming, state);
+ }
}
-bool EventRewriter::RewriteFunctionKeys(XEvent* event) {
- DCHECK(event->type == KeyPress || event->type == KeyRelease);
- XKeyEvent* xkey = &event->xkey;
- const KeySym keysym = XLookupKeysym(xkey, 0);
-
- KeySym remapped_native_keysym = 0;
- unsigned int remapped_native_mods = 0;
+void EventRewriter::RewriteFunctionKeys(const ui::KeyEvent& key_event,
+ MutableKeyState* state) {
+ CHECK(key_event.type() == ui::ET_KEY_PRESSED ||
+ key_event.type() == ui::ET_KEY_RELEASED);
+ MutableKeyState incoming = *state;
bool rewritten = false;
- // By default the top row (F1-F12) keys are special keys for back, forward,
- // brightness, volume, etc. However, windows for v2 apps can optionally
- // request raw function keys for these keys.
- bool top_row_keys_are_special_keys = !TopRowKeysAreFunctionKeys(event);
-
- if ((xkey->state & Mod4Mask) && top_row_keys_are_special_keys) {
- // Allow Search to avoid rewriting F1-F12.
- static const KeyboardRemapping kFkeysToFkeys[] = {
- { XK_F1, Mod4Mask, XK_F1, },
- { XK_F2, Mod4Mask, XK_F2, },
- { XK_F3, Mod4Mask, XK_F3, },
- { XK_F4, Mod4Mask, XK_F4, },
- { XK_F5, Mod4Mask, XK_F5, },
- { XK_F6, Mod4Mask, XK_F6, },
- { XK_F7, Mod4Mask, XK_F7, },
- { XK_F8, Mod4Mask, XK_F8, },
- { XK_F9, Mod4Mask, XK_F9, },
- { XK_F10, Mod4Mask, XK_F10, },
- { XK_F11, Mod4Mask, XK_F11, },
- { XK_F12, Mod4Mask, XK_F12, },
- };
-
- rewritten = RewriteWithKeyboardRemappingsByKeySym(
- kFkeysToFkeys,
- arraysize(kFkeysToFkeys),
- keysym,
- xkey->state,
- &remapped_native_keysym,
- &remapped_native_mods);
- }
-
- if (!rewritten) {
- static const KeyboardRemapping kFkeysToSpecialKeys[] = {
- { XK_F1, 0, XF86XK_Back, 0 },
- { XK_F2, 0, XF86XK_Forward, 0 },
- { XK_F3, 0, XF86XK_Reload, 0 },
- { XK_F4, 0, XF86XK_LaunchB, 0 },
- { XK_F5, 0, XF86XK_LaunchA, 0 },
- { XK_F6, 0, XF86XK_MonBrightnessDown, 0 },
- { XK_F7, 0, XF86XK_MonBrightnessUp, 0 },
- { XK_F8, 0, XF86XK_AudioMute, 0 },
- { XK_F9, 0, XF86XK_AudioLowerVolume, 0 },
- { XK_F10, 0, XF86XK_AudioRaiseVolume, 0 },
- };
-
- if (top_row_keys_are_special_keys) {
- // Rewrite the F1-F12 keys on a Chromebook keyboard to special keys.
- rewritten = RewriteWithKeyboardRemappingsByKeySym(
- kFkeysToSpecialKeys,
- arraysize(kFkeysToSpecialKeys),
- keysym,
- xkey->state,
- &remapped_native_keysym,
- &remapped_native_mods);
- } else if (xkey->state & Mod4Mask) {
- // Use Search + F1-F12 for the special keys.
- rewritten = RewriteWithKeyboardRemappingsByKeySym(
- kFkeysToSpecialKeys,
- arraysize(kFkeysToSpecialKeys),
- keysym,
- xkey->state & ~Mod4Mask,
- &remapped_native_keysym,
- &remapped_native_mods);
+ if ((incoming.key_code >= ui::VKEY_F1) &&
+ (incoming.key_code <= ui::VKEY_F24)) {
+ // By default the top row (F1-F12) keys are system keys for back, forward,
+ // brightness, volume, etc. However, windows for v2 apps can optionally
+ // request raw function keys for these keys.
+ bool top_row_keys_are_function_keys = TopRowKeysAreFunctionKeys(key_event);
+ bool search_is_pressed = (incoming.flags & ui::EF_COMMAND_DOWN) != 0;
+
+ // Search? Top Row Result
+ // ------- -------- ------
+ // No Fn Unchanged
+ // No System Fn -> System
+ // Yes Fn Fn -> System
+ // Yes System Search+Fn -> Fn
+ if (top_row_keys_are_function_keys == search_is_pressed) {
+ // Rewrite the F1-F12 keys on a Chromebook keyboard to system keys.
+ static const KeyboardRemapping kFkeysToSystemKeys[] = {
+ {ui::VKEY_F1, 0, ui::VKEY_BROWSER_BACK, 0},
+ {ui::VKEY_F2, 0, ui::VKEY_BROWSER_FORWARD, 0},
+ {ui::VKEY_F3, 0, ui::VKEY_BROWSER_REFRESH, 0},
+ {ui::VKEY_F4, 0, ui::VKEY_MEDIA_LAUNCH_APP2, 0},
+ {ui::VKEY_F5, 0, ui::VKEY_MEDIA_LAUNCH_APP1, 0},
+ {ui::VKEY_F6, 0, ui::VKEY_BRIGHTNESS_DOWN, 0},
+ {ui::VKEY_F7, 0, ui::VKEY_BRIGHTNESS_UP, 0},
+ {ui::VKEY_F8, 0, ui::VKEY_VOLUME_MUTE, 0},
+ {ui::VKEY_F9, 0, ui::VKEY_VOLUME_DOWN, 0},
+ {ui::VKEY_F10, 0, ui::VKEY_VOLUME_UP, 0},
+ };
+ MutableKeyState incoming_without_command = incoming;
+ incoming_without_command.flags &= ~ui::EF_COMMAND_DOWN;
+ rewritten =
+ RewriteWithKeyboardRemappingsByKeyCode(kFkeysToSystemKeys,
+ arraysize(kFkeysToSystemKeys),
+ incoming_without_command,
+ state);
+ } else if (search_is_pressed) {
+ // Allow Search to avoid rewriting F1-F12.
+ state->flags &= ~ui::EF_COMMAND_DOWN;
+ rewritten = true;
}
}
- if (!rewritten && (xkey->state & Mod4Mask)) {
+ if (!rewritten && (incoming.flags & ui::EF_COMMAND_DOWN)) {
// Remap Search+<number> to F<number>.
// We check the keycode here instead of the keysym, as these keys have
// different keysyms when modifiers are pressed, such as shift.
@@ -804,53 +593,47 @@ bool EventRewriter::RewriteFunctionKeys(XEvent* event) {
// should make layout-specific choices here. For eg. on a french keyboard
// "-" and "6" are the same key, so F11 will not be accessible.
static const KeyboardRemapping kNumberKeysToFkeys[] = {
- { XK_1, Mod4Mask, XK_F1, 0 },
- { XK_2, Mod4Mask, XK_F2, 0 },
- { XK_3, Mod4Mask, XK_F3, 0 },
- { XK_4, Mod4Mask, XK_F4, 0 },
- { XK_5, Mod4Mask, XK_F5, 0 },
- { XK_6, Mod4Mask, XK_F6, 0 },
- { XK_7, Mod4Mask, XK_F7, 0 },
- { XK_8, Mod4Mask, XK_F8, 0 },
- { XK_9, Mod4Mask, XK_F9, 0 },
- { XK_0, Mod4Mask, XK_F10, 0 },
- { XK_minus, Mod4Mask, XK_F11, 0 },
- { XK_equal, Mod4Mask, XK_F12, 0 }
- };
-
+ {ui::VKEY_1, ui::EF_COMMAND_DOWN, ui::VKEY_F1, 0},
+ {ui::VKEY_2, ui::EF_COMMAND_DOWN, ui::VKEY_F2, 0},
+ {ui::VKEY_3, ui::EF_COMMAND_DOWN, ui::VKEY_F3, 0},
+ {ui::VKEY_4, ui::EF_COMMAND_DOWN, ui::VKEY_F4, 0},
+ {ui::VKEY_5, ui::EF_COMMAND_DOWN, ui::VKEY_F5, 0},
+ {ui::VKEY_6, ui::EF_COMMAND_DOWN, ui::VKEY_F6, 0},
+ {ui::VKEY_7, ui::EF_COMMAND_DOWN, ui::VKEY_F7, 0},
+ {ui::VKEY_8, ui::EF_COMMAND_DOWN, ui::VKEY_F8, 0},
+ {ui::VKEY_9, ui::EF_COMMAND_DOWN, ui::VKEY_F9, 0},
+ {ui::VKEY_0, ui::EF_COMMAND_DOWN, ui::VKEY_F10, 0},
+ {ui::VKEY_OEM_MINUS, ui::EF_COMMAND_DOWN, ui::VKEY_F11, 0},
+ {ui::VKEY_OEM_PLUS, ui::EF_COMMAND_DOWN, ui::VKEY_F12, 0}};
rewritten = RewriteWithKeyboardRemappingsByKeyCode(
- kNumberKeysToFkeys,
- arraysize(kNumberKeysToFkeys),
- xkey->keycode,
- xkey->state,
- &remapped_native_keysym,
- &remapped_native_mods);
+ kNumberKeysToFkeys, arraysize(kNumberKeysToFkeys), incoming, state);
}
-
- if (!rewritten)
- return false;
-
- OverwriteEvent(event,
- NativeKeySymToNativeKeycode(remapped_native_keysym),
- remapped_native_mods);
- return true;
}
-void EventRewriter::RewriteLocatedEvent(XEvent* event) {
- DCHECK_EQ(GenericEvent, event->type);
- XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
- if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease)
+void EventRewriter::RewriteLocatedEvent(const ui::Event& event,
+ MutableKeyState* state) {
+ const PrefService* pref_service = GetPrefService();
+ if (!pref_service)
return;
// First, remap modifier masks.
- unsigned int remapped_native_modifiers = 0U;
- GetRemappedModifierMasks(xievent->mods.effective, &remapped_native_modifiers);
- xievent->mods.effective = remapped_native_modifiers;
+ state->flags = GetRemappedModifierMasks(*pref_service, event, state->flags);
+
+#if defined(USE_X11)
+ // TODO(kpschoedel): de-X11 with unified device ids from crbug.com/360377
+ XEvent* xevent = event.native_event();
+ if (!xevent || xevent->type != GenericEvent)
+ return;
+ XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
+ if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease)
+ return;
// Then, remap Alt+Button1 to Button3.
if ((xievent->evtype == XI_ButtonPress ||
pressed_device_ids_.count(xievent->sourceid)) &&
(xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) {
+ state->flags &= ~(ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON);
+ state->flags |= ui::EF_RIGHT_MOUSE_BUTTON;
xievent->mods.effective &= ~Mod1Mask;
xievent->detail = Button3;
if (xievent->evtype == XI_ButtonRelease) {
@@ -864,21 +647,13 @@ void EventRewriter::RewriteLocatedEvent(XEvent* event) {
pressed_device_ids_.insert(xievent->sourceid);
}
}
-}
-
-void EventRewriter::OverwriteEvent(XEvent* event,
- unsigned int new_native_keycode,
- unsigned int new_native_state) {
- DCHECK(event->type == KeyPress || event->type == KeyRelease);
- XKeyEvent* xkey = &event->xkey;
- xkey->keycode = new_native_keycode;
- xkey->state = new_native_state;
+#endif // defined(USE_X11)
}
EventRewriter::DeviceType EventRewriter::DeviceAddedInternal(
int device_id,
const std::string& device_name) {
- const DeviceType type = EventRewriter::GetDeviceType(device_name);
+ const DeviceType type = GetDeviceType(device_name);
if (type == kDeviceAppleKeyboard) {
VLOG(1) << "Apple keyboard '" << device_name << "' connected: "
<< "id=" << device_id;
@@ -889,4 +664,56 @@ EventRewriter::DeviceType EventRewriter::DeviceAddedInternal(
return type;
}
+#if defined(USE_X11)
+void EventRewriter::WillProcessEvent(const ui::PlatformEvent& event) {
+ XEvent* xevent = event;
+ if (xevent->type == GenericEvent) {
+ XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
+ if (xievent->evtype == XI_KeyPress || xievent->evtype == XI_KeyRelease) {
+ if (xievent->deviceid == xievent->sourceid)
+ DeviceKeyPressedOrReleased(xievent->deviceid);
+ }
+ }
+}
+
+void EventRewriter::DidProcessEvent(const ui::PlatformEvent& event) {
+}
+
+void EventRewriter::DeviceHierarchyChanged() {
+}
+
+void EventRewriter::DeviceAdded(int device_id) {
+ DCHECK_NE(XIAllDevices, device_id);
+ DCHECK_NE(XIAllMasterDevices, device_id);
+ if (device_id == XIAllDevices || device_id == XIAllMasterDevices) {
+ LOG(ERROR) << "Unexpected device_id passed: " << device_id;
+ return;
+ }
+
+ int ndevices_return = 0;
+ XIDeviceInfo* device_info =
+ XIQueryDevice(gfx::GetXDisplay(), device_id, &ndevices_return);
+
+ // Since |device_id| is neither XIAllDevices nor XIAllMasterDevices,
+ // the number of devices found should be either 0 (not found) or 1.
+ if (!device_info) {
+ LOG(ERROR) << "XIQueryDevice: Device ID " << device_id << " is unknown.";
+ return;
+ }
+
+ DCHECK_EQ(1, ndevices_return);
+ for (int i = 0; i < ndevices_return; ++i) {
+ DCHECK_EQ(device_id, device_info[i].deviceid); // see the comment above.
+ DCHECK(device_info[i].name);
+ DeviceAddedInternal(device_info[i].deviceid, device_info[i].name);
+ }
+
+ XIFreeDeviceInfo(device_info);
+}
+
+void EventRewriter::DeviceRemoved(int device_id) {
+ device_id_to_type_.erase(device_id);
+}
+#endif
+
} // namespace chromeos
« no previous file with comments | « chrome/browser/chromeos/events/event_rewriter.h ('k') | chrome/browser/chromeos/events/event_rewriter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698