Bug 1137561 part.6 Store some strings which may be inputted by the key with some modifier state before dispatching keydown event r=m_kato

This commit is contained in:
Masayuki Nakano 2016-03-16 13:47:49 +09:00
parent 22e9178025
commit 1728345f86
2 changed files with 122 additions and 72 deletions

View File

@ -669,6 +669,8 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
, mModKeyState(aModKeyState)
, mVirtualKeyCode(0)
, mOriginalVirtualKeyCode(0)
, shiftedLatinChar(0)
, unshiftedLatinChar(0)
, mScanCode(0)
, mIsExtended(false)
, mIsDeadKey(false)
@ -857,6 +859,14 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
(IsFollowedByDeadCharMessage() ||
keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState));
mIsPrintableKey = KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode);
// Compute some strings which may be inputted by the key with various
// modifier state if this key event won't cause text input actually.
// They will be used for setting alternativeCharCodes in the callback
// method which will be called by TextEventDispatcher.
if (IsKeyDownMessage() && NeedsToHandleWithoutFollowingCharMessages()) {
ComputeInputtingStringWithKeyboardLayout();
}
}
void
@ -2066,84 +2076,94 @@ NativeKey::DispatchPluginEventsAndDiscardsCharMessages() const
return false;
}
void
NativeKey::ComputeInputtingStringWithKeyboardLayout()
{
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
if (KeyboardLayout::IsPrintableCharKey(mVirtualKeyCode)) {
inputtingChars = mCommittedCharsAndModifiers;
} else {
inputtingChars.Clear();
}
shiftedChars.Clear();
unshiftedChars.Clear();
shiftedLatinChar = unshiftedLatinChar = 0;
// XXX How about when Win key is pressed?
if (mModKeyState.IsControl() == mModKeyState.IsAlt()) {
return;
}
ModifierKeyState capsLockState(
mModKeyState.GetModifiers() & MODIFIER_CAPSLOCK);
unshiftedChars =
keyboardLayout->GetUniCharsAndModifiers(mVirtualKeyCode, capsLockState);
capsLockState.Set(MODIFIER_SHIFT);
shiftedChars =
keyboardLayout->GetUniCharsAndModifiers(mVirtualKeyCode, capsLockState);
// The current keyboard cannot input alphabets or numerics,
// we should append them for Shortcut/Access keys.
// E.g., for Cyrillic keyboard layout.
capsLockState.Unset(MODIFIER_SHIFT);
WidgetUtils::GetLatinCharCodeForKeyCode(mDOMKeyCode,
capsLockState.GetModifiers(),
&unshiftedLatinChar,
&shiftedLatinChar);
// If the shiftedLatinChar isn't 0, the key code is NS_VK_[A-Z].
if (shiftedLatinChar) {
// If the produced characters of the key on current keyboard layout
// are same as computed Latin characters, we shouldn't append the
// Latin characters to alternativeCharCode.
if (unshiftedLatinChar == unshiftedChars.mChars[0] &&
shiftedLatinChar == shiftedChars.mChars[0]) {
shiftedLatinChar = unshiftedLatinChar = 0;
}
} else if (unshiftedLatinChar) {
// If the shiftedLatinChar is 0, the keyCode doesn't produce
// alphabet character. At that time, the character may be produced
// with Shift key. E.g., on French keyboard layout, NS_VK_PERCENT
// key produces LATIN SMALL LETTER U WITH GRAVE (U+00F9) without
// Shift key but with Shift key, it produces '%'.
// If the unshiftedLatinChar is produced by the key on current
// keyboard layout, we shouldn't append it to alternativeCharCode.
if (unshiftedLatinChar == unshiftedChars.mChars[0] ||
unshiftedLatinChar == shiftedChars.mChars[0]) {
unshiftedLatinChar = 0;
}
}
if (!mModKeyState.IsControl()) {
return;
}
// If the charCode is not ASCII character, we should replace the
// charCode with ASCII character only when Ctrl is pressed.
// But don't replace the charCode when the charCode is not same as
// unmodified characters. In such case, Ctrl is sometimes used for a
// part of character inputting key combination like Shift.
uint32_t ch =
mModKeyState.IsShift() ? shiftedLatinChar : unshiftedLatinChar;
if (!ch) {
return;
}
if (inputtingChars.IsEmpty() ||
inputtingChars.UniCharsCaseInsensitiveEqual(
mModKeyState.IsShift() ? shiftedChars : unshiftedChars)) {
inputtingChars.Clear();
inputtingChars.Append(ch, mModKeyState.GetModifiers());
}
}
bool
NativeKey::DispatchKeyPressEventsWithKeyboardLayout() const
{
MOZ_ASSERT(IsKeyDownMessage());
MOZ_ASSERT(!mIsDeadKey);
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
UniCharsAndModifiers inputtingChars(mCommittedCharsAndModifiers);
UniCharsAndModifiers shiftedChars;
UniCharsAndModifiers unshiftedChars;
uint32_t shiftedLatinChar = 0;
uint32_t unshiftedLatinChar = 0;
if (!KeyboardLayout::IsPrintableCharKey(mVirtualKeyCode)) {
inputtingChars.Clear();
}
if (mModKeyState.IsControl() ^ mModKeyState.IsAlt()) {
ModifierKeyState capsLockState(
mModKeyState.GetModifiers() & MODIFIER_CAPSLOCK);
unshiftedChars =
keyboardLayout->GetUniCharsAndModifiers(mVirtualKeyCode, capsLockState);
capsLockState.Set(MODIFIER_SHIFT);
shiftedChars =
keyboardLayout->GetUniCharsAndModifiers(mVirtualKeyCode, capsLockState);
// The current keyboard cannot input alphabets or numerics,
// we should append them for Shortcut/Access keys.
// E.g., for Cyrillic keyboard layout.
capsLockState.Unset(MODIFIER_SHIFT);
WidgetUtils::GetLatinCharCodeForKeyCode(mDOMKeyCode,
capsLockState.GetModifiers(),
&unshiftedLatinChar,
&shiftedLatinChar);
// If the shiftedLatinChar isn't 0, the key code is NS_VK_[A-Z].
if (shiftedLatinChar) {
// If the produced characters of the key on current keyboard layout
// are same as computed Latin characters, we shouldn't append the
// Latin characters to alternativeCharCode.
if (unshiftedLatinChar == unshiftedChars.mChars[0] &&
shiftedLatinChar == shiftedChars.mChars[0]) {
shiftedLatinChar = unshiftedLatinChar = 0;
}
} else if (unshiftedLatinChar) {
// If the shiftedLatinChar is 0, the keyCode doesn't produce
// alphabet character. At that time, the character may be produced
// with Shift key. E.g., on French keyboard layout, NS_VK_PERCENT
// key produces LATIN SMALL LETTER U WITH GRAVE (U+00F9) without
// Shift key but with Shift key, it produces '%'.
// If the unshiftedLatinChar is produced by the key on current
// keyboard layout, we shouldn't append it to alternativeCharCode.
if (unshiftedLatinChar == unshiftedChars.mChars[0] ||
unshiftedLatinChar == shiftedChars.mChars[0]) {
unshiftedLatinChar = 0;
}
}
// If the charCode is not ASCII character, we should replace the
// charCode with ASCII character only when Ctrl is pressed.
// But don't replace the charCode when the charCode is not same as
// unmodified characters. In such case, Ctrl is sometimes used for a
// part of character inputting key combination like Shift.
if (mModKeyState.IsControl()) {
uint32_t ch =
mModKeyState.IsShift() ? shiftedLatinChar : unshiftedLatinChar;
if (ch &&
(!inputtingChars.mLength ||
inputtingChars.UniCharsCaseInsensitiveEqual(
mModKeyState.IsShift() ? shiftedChars : unshiftedChars))) {
inputtingChars.Clear();
inputtingChars.Append(ch, mModKeyState.GetModifiers());
}
}
}
if (inputtingChars.IsEmpty() &&
shiftedChars.IsEmpty() && unshiftedChars.IsEmpty()) {
nsresult rv = mDispatcher->BeginNativeInputTransaction();

View File

@ -293,6 +293,29 @@ private:
// indicates both the dead characters and the base characters.
UniCharsAndModifiers mCommittedCharsAndModifiers;
// Following strings are computed by
// ComputeInputtingStringWithKeyboardLayout() which is typically called
// before dispatching keydown event.
// TODO: following new member names are temporary name for making the changes
// in KeyboardLayout.cpp easier to read. They will be renamed following
// patch.
// mInputtingStringAndModifiers's string is the string to be
// inputted into the focused editor and its modifier state is proper
// modifier state for inputting the string into the editor.
UniCharsAndModifiers inputtingChars;
// mShiftedString is the string to be inputted into the editor with
// current modifier state with active shift state.
UniCharsAndModifiers shiftedChars;
// mUnshiftedString is the string to be inputted into the editor with
// current modifier state without shift state.
UniCharsAndModifiers unshiftedChars;
// Following integers are computed by
// ComputeInputtingStringWithKeyboardLayout() which is typically called
// before dispatching keydown event. The meaning of these values is same
// as charCode.
uint32_t shiftedLatinChar;
uint32_t unshiftedLatinChar;
WORD mScanCode;
bool mIsExtended;
bool mIsDeadKey;
@ -484,6 +507,13 @@ private:
* or Backspace.
*/
bool NeedsToHandleWithoutFollowingCharMessages() const;
/**
* ComputeInputtingStringWithKeyboardLayout() computes string to be inputted
* with the key and the modifier state, without shift state and with shift
* state.
*/
void ComputeInputtingStringWithKeyboardLayout();
};
class KeyboardLayout