Bug 1137561 part.8 Implement WinTextEventDispatcherListener::WillDispatchKeyboardEvent() r=m_kato

This commit is contained in:
Masayuki Nakano 2016-03-16 13:47:49 +09:00
Родитель 697c992f55
Коммит bd594893c8
3 изменённых файлов: 118 добавлений и 96 удалений

Просмотреть файл

@ -1533,7 +1533,7 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
// keypress for almost all keys
if (NeedsToHandleWithoutFollowingCharMessages()) {
return (DispatchPluginEventsAndDiscardsCharMessages() ||
DispatchKeyPressEventsWithKeyboardLayout());
DispatchKeyPressEventsWithoutCharMessage());
}
MSG followingCharMsg;
@ -1560,7 +1560,7 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
return false;
}
return DispatchKeyPressEventsWithKeyboardLayout();
return DispatchKeyPressEventsWithoutCharMessage();
}
bool
@ -2159,113 +2159,125 @@ NativeKey::ComputeInputtingStringWithKeyboardLayout()
}
bool
NativeKey::DispatchKeyPressEventsWithKeyboardLayout() const
NativeKey::DispatchKeyPressEventsWithoutCharMessage() const
{
MOZ_ASSERT(IsKeyDownMessage());
MOZ_ASSERT(!mIsDeadKey);
if (mInputtingStringAndModifiers.IsEmpty() &&
mShiftedString.IsEmpty() && mUnshiftedString.IsEmpty()) {
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
keypressEvent.keyCode = mDOMKeyCode;
nsEventStatus status = InitKeyEvent(keypressEvent, mModKeyState);
mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
const_cast<NativeKey*>(this));
return status == nsEventStatus_eConsumeNoDefault;
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
if (mInputtingStringAndModifiers.IsEmpty() &&
mShiftedString.IsEmpty() && mUnshiftedString.IsEmpty()) {
keypressEvent.keyCode = mDOMKeyCode;
}
nsEventStatus status = InitKeyEvent(keypressEvent, mModKeyState);
mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
const_cast<NativeKey*>(this));
return status == nsEventStatus_eConsumeNoDefault;
}
void
NativeKey::WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndex)
{
uint32_t longestLength =
std::max(mInputtingStringAndModifiers.mLength,
std::max(mShiftedString.mLength, mUnshiftedString.mLength));
uint32_t skipUniChars = longestLength - mInputtingStringAndModifiers.mLength;
uint32_t skipShiftedChars = longestLength - mShiftedString.mLength;
uint32_t skipUnshiftedChars = longestLength - mUnshiftedString.mLength;
bool defaultPrevented = false;
for (uint32_t cnt = 0; cnt < longestLength; cnt++) {
uint16_t uniChar, shiftedChar, unshiftedChar;
uniChar = shiftedChar = unshiftedChar = 0;
ModifierKeyState modKeyState(mModKeyState);
if (skipUniChars <= cnt) {
if (cnt - skipUniChars < mInputtingStringAndModifiers.mLength) {
// If key in combination with Alt and/or Ctrl produces a different
// character than without them then do not report these flags
// because it is separate keyboard layout shift state. If dead-key
// and base character does not produce a valid composite character
// then both produced dead-key character and following base
// character may have different modifier flags, too.
modKeyState.Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT |
MODIFIER_ALTGRAPH | MODIFIER_CAPSLOCK);
modKeyState.Set(
mInputtingStringAndModifiers.mModifiers[cnt - skipUniChars]);
}
uniChar = mInputtingStringAndModifiers.mChars[cnt - skipUniChars];
}
if (skipShiftedChars <= cnt)
shiftedChar = mShiftedString.mChars[cnt - skipShiftedChars];
if (skipUnshiftedChars <= cnt)
unshiftedChar = mUnshiftedString.mChars[cnt - skipUnshiftedChars];
AutoTArray<AlternativeCharCode, 5> altArray;
if (aIndex >= longestLength) {
return;
}
if (shiftedChar || unshiftedChar) {
AlternativeCharCode chars(unshiftedChar, shiftedChar);
nsTArray<AlternativeCharCode>& altArray = aKeyboardEvent.alternativeCharCodes;
uint16_t shiftedChar = 0, unshiftedChar = 0;
if (skipUniChars <= aIndex) {
// XXX Modifying modifier state of aKeyboardEvent is illegal, but no way
// to set different modifier state per keypress event except this
// hack. Note that ideally, dead key should cause composition events
// instead of keypress events, though.
if (aIndex - skipUniChars < mInputtingStringAndModifiers.mLength) {
ModifierKeyState modKeyState(mModKeyState);
// If key in combination with Alt and/or Ctrl produces a different
// character than without them then do not report these flags
// because it is separate keyboard layout shift state. If dead-key
// and base character does not produce a valid composite character
// then both produced dead-key character and following base
// character may have different modifier flags, too.
modKeyState.Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT |
MODIFIER_ALTGRAPH | MODIFIER_CAPSLOCK);
modKeyState.Set(
mInputtingStringAndModifiers.mModifiers[aIndex - skipUniChars]);
modKeyState.InitInputEvent(aKeyboardEvent);
}
uint16_t uniChar =
mInputtingStringAndModifiers.mChars[aIndex - skipUniChars];
if (aKeyboardEvent.mMessage == eKeyPress) {
// charCode is set from mKeyValue but e.g., when Ctrl key is pressed,
// the value should indicate an ASCII character for backward
// compatibility instead of inputting character without the modifiers.
aKeyboardEvent.charCode = uniChar;
MOZ_ASSERT(!aKeyboardEvent.keyCode);
} else if (uniChar) {
// If the event is not keypress event, we should set charCode as
// first alternative char code since the char code value is necessary
// for shortcut key handlers at looking for a proper handler.
AlternativeCharCode chars(0, 0);
if (!aKeyboardEvent.IsShift()) {
chars.mUnshiftedCharCode = uniChar;
} else {
chars.mShiftedCharCode = uniChar;
}
altArray.AppendElement(chars);
}
if (cnt == longestLength - 1) {
if (mUnshiftedLatinChar || mShiftedLatinChar) {
AlternativeCharCode chars(mUnshiftedLatinChar, mShiftedLatinChar);
altArray.AppendElement(chars);
}
// Typically, following virtual keycodes are used for a key which can
// input the character. However, these keycodes are also used for
// other keys on some keyboard layout. E.g., in spite of Shift+'1'
// inputs '+' on Thai keyboard layout, a key which is at '=/+'
// key on ANSI keyboard layout is VK_OEM_PLUS. Native applications
// handle it as '+' key if Ctrl key is pressed.
char16_t charForOEMKeyCode = 0;
switch (mVirtualKeyCode) {
case VK_OEM_PLUS: charForOEMKeyCode = '+'; break;
case VK_OEM_COMMA: charForOEMKeyCode = ','; break;
case VK_OEM_MINUS: charForOEMKeyCode = '-'; break;
case VK_OEM_PERIOD: charForOEMKeyCode = '.'; break;
}
if (charForOEMKeyCode &&
charForOEMKeyCode != mUnshiftedString.mChars[0] &&
charForOEMKeyCode != mShiftedString.mChars[0] &&
charForOEMKeyCode != mUnshiftedLatinChar &&
charForOEMKeyCode != mShiftedLatinChar) {
AlternativeCharCode OEMChars(charForOEMKeyCode, charForOEMKeyCode);
altArray.AppendElement(OEMChars);
}
}
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
// We should optimize this with improving TextEventDispatcher later.
WidgetKeyboardEvent keypressEvent(true, eKeyPress, mWidget);
keypressEvent.charCode = uniChar;
keypressEvent.alternativeCharCodes.AppendElements(altArray);
nsEventStatus status = InitKeyEvent(keypressEvent, modKeyState);
mDispatcher->MaybeDispatchKeypressEvents(keypressEvent, status,
const_cast<NativeKey*>(this));
defaultPrevented =
(status == nsEventStatus_eConsumeNoDefault || defaultPrevented);
if (mWidget->Destroyed()) {
return true;
}
}
return defaultPrevented;
if (skipShiftedChars <= aIndex) {
shiftedChar = mShiftedString.mChars[aIndex - skipShiftedChars];
}
if (skipUnshiftedChars <= aIndex) {
unshiftedChar = mUnshiftedString.mChars[aIndex - skipUnshiftedChars];
}
if (shiftedChar || unshiftedChar) {
AlternativeCharCode chars(unshiftedChar, shiftedChar);
altArray.AppendElement(chars);
}
if (aIndex == longestLength - 1) {
if (mUnshiftedLatinChar || mShiftedLatinChar) {
AlternativeCharCode chars(mUnshiftedLatinChar, mShiftedLatinChar);
altArray.AppendElement(chars);
}
// Typically, following virtual keycodes are used for a key which can
// input the character. However, these keycodes are also used for
// other keys on some keyboard layout. E.g., in spite of Shift+'1'
// inputs '+' on Thai keyboard layout, a key which is at '=/+'
// key on ANSI keyboard layout is VK_OEM_PLUS. Native applications
// handle it as '+' key if Ctrl key is pressed.
char16_t charForOEMKeyCode = 0;
switch (mVirtualKeyCode) {
case VK_OEM_PLUS: charForOEMKeyCode = '+'; break;
case VK_OEM_COMMA: charForOEMKeyCode = ','; break;
case VK_OEM_MINUS: charForOEMKeyCode = '-'; break;
case VK_OEM_PERIOD: charForOEMKeyCode = '.'; break;
}
if (charForOEMKeyCode &&
charForOEMKeyCode != mUnshiftedString.mChars[0] &&
charForOEMKeyCode != mShiftedString.mChars[0] &&
charForOEMKeyCode != mUnshiftedLatinChar &&
charForOEMKeyCode != mShiftedLatinChar) {
AlternativeCharCode OEMChars(charForOEMKeyCode, charForOEMKeyCode);
altArray.AppendElement(OEMChars);
}
}
}
bool

Просмотреть файл

@ -269,6 +269,13 @@ public:
*/
bool HandleAppCommandMessage() const;
/**
* Callback of TextEventDispatcherListener::WillDispatchKeyboardEvent().
* This method sets alternative char codes of aKeyboardEvent.
*/
void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndex);
private:
RefPtr<nsWindowBase> mWidget;
RefPtr<TextEventDispatcher> mDispatcher;
@ -476,10 +483,11 @@ private:
bool DispatchCommandEvent(uint32_t aEventCommand) const;
/**
* DispatchKeyPressEventsWithKeyboardLayout() dispatches keypress event(s)
* with the information provided by KeyboardLayout class.
* DispatchKeyPressEventsWithoutCharMessage() dispatches keypress event(s)
* without char messages. So, this should be used only when there are no
* following char messages.
*/
bool DispatchKeyPressEventsWithKeyboardLayout() const;
bool DispatchKeyPressEventsWithoutCharMessage() const;
/**
* Remove all following WM_CHAR, WM_SYSCHAR and WM_DEADCHAR messages for the

Просмотреть файл

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "KeyboardLayout.h"
#include "mozilla/TextEventDispatcher.h"
#include "mozilla/widget/IMEData.h"
#include "nsWindow.h"
@ -68,7 +69,8 @@ WinTextEventDispatcherListener::WillDispatchKeyboardEvent(
uint32_t aIndexOfKeypress,
void* aData)
{
// TODO: Implement this method later.
static_cast<NativeKey*>(aData)->
WillDispatchKeyboardEvent(aKeyboardEvent, aIndexOfKeypress);
}
} // namespace widget