зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1154183 part.1 Move shortcut/access key candidate list creators from nsContentUtils to WidgetKeyboardEvent r=smaug
MozReview-Commit-ID: Ied6qEUc2Kz
This commit is contained in:
Родитель
358dd6f8a1
Коммит
963976b46d
|
@ -4905,188 +4905,6 @@ nsContentUtils::GetLocalizedEllipsis()
|
|||
return nsDependentString(sBuf);
|
||||
}
|
||||
|
||||
static bool
|
||||
HasASCIIDigit(const nsTArray<nsShortcutCandidate>& aCandidates)
|
||||
{
|
||||
for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
|
||||
uint32_t ch = aCandidates[i].mCharCode;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2)
|
||||
{
|
||||
return aChar1 == aChar2 ||
|
||||
(IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
|
||||
ToLowerCase(char16_t(aChar1)) == ToLowerCase(char16_t(aChar2)));
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCaseChangeableChar(uint32_t aChar)
|
||||
{
|
||||
return IS_IN_BMP(aChar) &&
|
||||
ToLowerCase(char16_t(aChar)) != ToUpperCase(char16_t(aChar));
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::GetAccelKeyCandidates(nsIDOMKeyEvent* aDOMKeyEvent,
|
||||
nsTArray<nsShortcutCandidate>& aCandidates)
|
||||
{
|
||||
NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
|
||||
|
||||
nsAutoString eventType;
|
||||
aDOMKeyEvent->AsEvent()->GetType(eventType);
|
||||
// Don't process if aDOMKeyEvent is not a keypress event.
|
||||
if (!eventType.EqualsLiteral("keypress"))
|
||||
return;
|
||||
|
||||
WidgetKeyboardEvent* nativeKeyEvent =
|
||||
aDOMKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
|
||||
if (nativeKeyEvent) {
|
||||
NS_ASSERTION(nativeKeyEvent->mClass == eKeyboardEventClass,
|
||||
"wrong type of native event");
|
||||
// nsShortcutCandidate::mCharCode is a candidate charCode.
|
||||
// nsShoftcutCandidate::mIgnoreShift means the mCharCode should be tried to
|
||||
// execute a command with/without shift key state. If this is TRUE, the
|
||||
// shifted key state should be ignored. Otherwise, don't ignore the state.
|
||||
// the priority of the charCodes are (shift key is not pressed):
|
||||
// 0: charCode/false,
|
||||
// 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
|
||||
// the priority of the charCodes are (shift key is pressed):
|
||||
// 0: charCode/false,
|
||||
// 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
|
||||
// 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
|
||||
if (nativeKeyEvent->charCode) {
|
||||
nsShortcutCandidate key(nativeKeyEvent->charCode, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
|
||||
uint32_t len = nativeKeyEvent->alternativeCharCodes.Length();
|
||||
if (!nativeKeyEvent->IsShift()) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uint32_t ch =
|
||||
nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
|
||||
if (!ch || ch == nativeKeyEvent->charCode)
|
||||
continue;
|
||||
|
||||
nsShortcutCandidate key(ch, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
// If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
|
||||
// this keyboard layout is AZERTY or similar layout, probably.
|
||||
// In this case, Accel+[0-9] should be accessible without shift key.
|
||||
// However, the priority should be lowest.
|
||||
if (!HasASCIIDigit(aCandidates)) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uint32_t ch =
|
||||
nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
nsShortcutCandidate key(ch, false);
|
||||
aCandidates.AppendElement(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uint32_t ch = nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
|
||||
if (!ch)
|
||||
continue;
|
||||
|
||||
if (ch != nativeKeyEvent->charCode) {
|
||||
nsShortcutCandidate key(ch, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
|
||||
// If the char is an alphabet, the shift key state should not be
|
||||
// ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
|
||||
|
||||
// And checking the charCode is same as unshiftedCharCode too.
|
||||
// E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
|
||||
uint32_t unshiftCh =
|
||||
nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
|
||||
if (CharsCaseInsensitiveEqual(ch, unshiftCh))
|
||||
continue;
|
||||
|
||||
// On the Hebrew keyboard layout on Windows, the unshifted char is a
|
||||
// localized character but the shifted char is a Latin alphabet,
|
||||
// then, we should not execute without the shift state. See bug 433192.
|
||||
if (IsCaseChangeableChar(ch))
|
||||
continue;
|
||||
|
||||
// Setting the alternative charCode candidates for retry without shift
|
||||
// key state only when the shift key is pressed.
|
||||
nsShortcutCandidate key(ch, true);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for "Space" key. With some keyboard layouts, "Space" with
|
||||
// or without Shift key causes non-ASCII space. For such keyboard layouts,
|
||||
// we should guarantee that the key press works as an ASCII white space key
|
||||
// press.
|
||||
if (nativeKeyEvent->mCodeNameIndex == CODE_NAME_INDEX_Space &&
|
||||
nativeKeyEvent->charCode != static_cast<uint32_t>(' ')) {
|
||||
nsShortcutCandidate spaceKey(static_cast<uint32_t>(' '), false);
|
||||
aCandidates.AppendElement(spaceKey);
|
||||
}
|
||||
} else {
|
||||
uint32_t charCode;
|
||||
aDOMKeyEvent->GetCharCode(&charCode);
|
||||
if (charCode) {
|
||||
nsShortcutCandidate key(charCode, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::GetAccessKeyCandidates(WidgetKeyboardEvent* aNativeKeyEvent,
|
||||
nsTArray<uint32_t>& aCandidates)
|
||||
{
|
||||
NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
|
||||
|
||||
// return the lower cased charCode candidates for access keys.
|
||||
// the priority of the charCodes are:
|
||||
// 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
|
||||
// 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
|
||||
if (aNativeKeyEvent->charCode) {
|
||||
uint32_t ch = aNativeKeyEvent->charCode;
|
||||
if (IS_IN_BMP(ch))
|
||||
ch = ToLowerCase(char16_t(ch));
|
||||
aCandidates.AppendElement(ch);
|
||||
}
|
||||
for (uint32_t i = 0;
|
||||
i < aNativeKeyEvent->alternativeCharCodes.Length(); ++i) {
|
||||
uint32_t ch[2] =
|
||||
{ aNativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode,
|
||||
aNativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode };
|
||||
for (uint32_t j = 0; j < 2; ++j) {
|
||||
if (!ch[j])
|
||||
continue;
|
||||
if (IS_IN_BMP(ch[j]))
|
||||
ch[j] = ToLowerCase(char16_t(ch[j]));
|
||||
// Don't append the charCode that was already appended.
|
||||
if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex)
|
||||
aCandidates.AppendElement(ch[j]);
|
||||
}
|
||||
}
|
||||
// Special case for "Space" key. With some keyboard layouts, "Space" with
|
||||
// or without Shift key causes non-ASCII space. For such keyboard layouts,
|
||||
// we should guarantee that the key press works as an ASCII white space key
|
||||
// press.
|
||||
if (aNativeKeyEvent->mCodeNameIndex == CODE_NAME_INDEX_Space &&
|
||||
aNativeKeyEvent->charCode != static_cast<uint32_t>(' ')) {
|
||||
aCandidates.AppendElement(static_cast<uint32_t>(' '));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::AddScriptBlocker()
|
||||
|
|
|
@ -171,15 +171,6 @@ struct EventNameMapping
|
|||
mozilla::EventClassID mEventClassID;
|
||||
};
|
||||
|
||||
struct nsShortcutCandidate {
|
||||
nsShortcutCandidate(uint32_t aCharCode, bool aIgnoreShift) :
|
||||
mCharCode(aCharCode), mIgnoreShift(aIgnoreShift)
|
||||
{
|
||||
}
|
||||
uint32_t mCharCode;
|
||||
bool mIgnoreShift;
|
||||
};
|
||||
|
||||
typedef void (*CallOnRemoteChildFunction) (mozilla::dom::TabParent* aTabParent,
|
||||
void* aArg);
|
||||
|
||||
|
@ -1511,27 +1502,6 @@ public:
|
|||
*/
|
||||
static const nsDependentString GetLocalizedEllipsis();
|
||||
|
||||
/**
|
||||
* Get the candidates for accelkeys for aDOMKeyEvent.
|
||||
*
|
||||
* @param aDOMKeyEvent [in] the key event for accelkey handling.
|
||||
* @param aCandidates [out] the candidate shortcut key combination list.
|
||||
* the first item is most preferred.
|
||||
*/
|
||||
static void GetAccelKeyCandidates(nsIDOMKeyEvent* aDOMKeyEvent,
|
||||
nsTArray<nsShortcutCandidate>& aCandidates);
|
||||
|
||||
/**
|
||||
* Get the candidates for accesskeys for aNativeKeyEvent.
|
||||
*
|
||||
* @param aNativeKeyEvent [in] the key event for accesskey handling.
|
||||
* @param aCandidates [out] the candidate access key list.
|
||||
* the first item is most preferred.
|
||||
*/
|
||||
static void GetAccessKeyCandidates(
|
||||
mozilla::WidgetKeyboardEvent* aNativeKeyEvent,
|
||||
nsTArray<uint32_t>& aCandidates);
|
||||
|
||||
/**
|
||||
* Hide any XUL popups associated with aDocument, including any documents
|
||||
* displayed in child frames. Does nothing if aDocument is null.
|
||||
|
|
|
@ -733,7 +733,7 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
(modifierMask == Prefs::ChromeAccessModifierMask() ||
|
||||
modifierMask == Prefs::ContentAccessModifierMask())) {
|
||||
AutoTArray<uint32_t, 10> accessCharCodes;
|
||||
nsContentUtils::GetAccessKeyCandidates(keyEvent, accessCharCodes);
|
||||
keyEvent->GetAccessKeyCandidates(accessCharCodes);
|
||||
|
||||
if (HandleAccessKey(aPresContext, accessCharCodes,
|
||||
keyEvent->mFlags.mIsTrusted, modifierMask)) {
|
||||
|
|
|
@ -140,18 +140,21 @@ nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent)
|
|||
if (!key)
|
||||
return NS_OK;
|
||||
|
||||
AutoTArray<nsShortcutCandidate, 10> accessKeys;
|
||||
nsContentUtils::GetAccelKeyCandidates(key, accessKeys);
|
||||
WidgetKeyboardEvent* nativeKeyboardEvent =
|
||||
aEvent->WidgetEventPtr()->AsKeyboardEvent();
|
||||
MOZ_ASSERT(nativeKeyboardEvent);
|
||||
AutoShortcutKeyCandidateArray shortcutKeys;
|
||||
nativeKeyboardEvent->GetShortcutKeyCandidates(shortcutKeys);
|
||||
|
||||
if (accessKeys.IsEmpty()) {
|
||||
if (shortcutKeys.IsEmpty()) {
|
||||
ExecuteMatchedHandlers(key, 0, IgnoreModifierState());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < accessKeys.Length(); ++i) {
|
||||
for (uint32_t i = 0; i < shortcutKeys.Length(); ++i) {
|
||||
IgnoreModifierState ignoreModifierState;
|
||||
ignoreModifierState.mShift = accessKeys[i].mIgnoreShift;
|
||||
if (ExecuteMatchedHandlers(key, accessKeys[i].mCharCode,
|
||||
ignoreModifierState.mShift = shortcutKeys[i].mIgnoreShift;
|
||||
if (ExecuteMatchedHandlers(key, shortcutKeys[i].mCharCode,
|
||||
ignoreModifierState)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -543,17 +543,21 @@ nsXBLWindowKeyHandler::WalkHandlersInternal(nsIDOMKeyEvent* aKeyEvent,
|
|||
bool aExecute,
|
||||
bool* aOutReservedForChrome)
|
||||
{
|
||||
AutoTArray<nsShortcutCandidate, 10> accessKeys;
|
||||
nsContentUtils::GetAccelKeyCandidates(aKeyEvent, accessKeys);
|
||||
WidgetKeyboardEvent* nativeKeyboardEvent =
|
||||
aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
|
||||
MOZ_ASSERT(nativeKeyboardEvent);
|
||||
|
||||
if (accessKeys.IsEmpty()) {
|
||||
AutoShortcutKeyCandidateArray shortcutKeys;
|
||||
nativeKeyboardEvent->GetShortcutKeyCandidates(shortcutKeys);
|
||||
|
||||
if (shortcutKeys.IsEmpty()) {
|
||||
return WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler,
|
||||
0, IgnoreModifierState(),
|
||||
aExecute, aOutReservedForChrome);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < accessKeys.Length(); ++i) {
|
||||
nsShortcutCandidate &key = accessKeys[i];
|
||||
for (uint32_t i = 0; i < shortcutKeys.Length(); ++i) {
|
||||
ShortcutKeyCandidate& key = shortcutKeys[i];
|
||||
IgnoreModifierState ignoreModifierState;
|
||||
ignoreModifierState.mShift = key.mIgnoreShift;
|
||||
if (WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler,
|
||||
|
|
|
@ -167,8 +167,9 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
AutoTArray<uint32_t, 10> accessKeys;
|
||||
WidgetKeyboardEvent* nativeKeyEvent =
|
||||
aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
|
||||
if (nativeKeyEvent)
|
||||
nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, accessKeys);
|
||||
if (nativeKeyEvent) {
|
||||
nativeKeyEvent->GetAccessKeyCandidates(accessKeys);
|
||||
}
|
||||
if (accessKeys.IsEmpty() && charCode)
|
||||
accessKeys.AppendElement(charCode);
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
|
||||
if (nativeKeyEvent) {
|
||||
AutoTArray<uint32_t, 10> keys;
|
||||
nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, keys);
|
||||
nativeKeyEvent->GetAccessKeyCandidates(keys);
|
||||
hasAccessKeyCandidates = !keys.IsEmpty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
/**
|
||||
* XXX Following enums should be in BasicEvents.h. However, currently, it's
|
||||
* impossible to use foward delearation for enum.
|
||||
|
@ -139,6 +141,10 @@ class WidgetEventTime;
|
|||
|
||||
// TextEvents.h
|
||||
struct AlternativeCharCode;
|
||||
struct ShortcutKeyCandidate;
|
||||
|
||||
typedef nsTArray<ShortcutKeyCandidate> ShortcutKeyCandidateArray;
|
||||
typedef AutoTArray<ShortcutKeyCandidate, 10> AutoShortcutKeyCandidateArray;
|
||||
|
||||
// TextRange.h
|
||||
struct TextRangeStyle;
|
||||
|
|
|
@ -70,6 +70,26 @@ struct AlternativeCharCode
|
|||
uint32_t mShiftedCharCode;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::ShortcutKeyCandidate
|
||||
*
|
||||
* This stores a candidate of shortcut key combination.
|
||||
******************************************************************************/
|
||||
|
||||
struct ShortcutKeyCandidate
|
||||
{
|
||||
ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
|
||||
: mCharCode(aCharCode)
|
||||
, mIgnoreShift(aIgnoreShift)
|
||||
{
|
||||
}
|
||||
// The charCode value which must match keyboard shortcut definition.
|
||||
uint32_t mCharCode;
|
||||
// true if Shift state can be ignored. Otherwise, Shift key state must
|
||||
// match keyboard shortcut definition.
|
||||
bool mIgnoreShift;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::WidgetKeyboardEvent
|
||||
******************************************************************************/
|
||||
|
@ -211,6 +231,22 @@ public:
|
|||
return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the candidates for shortcut key.
|
||||
*
|
||||
* @param aCandidates [out] the candidate shortcut key combination list.
|
||||
* the first item is most preferred.
|
||||
*/
|
||||
void GetShortcutKeyCandidates(ShortcutKeyCandidateArray& aCandidates);
|
||||
|
||||
/**
|
||||
* Get the candidates for access key.
|
||||
*
|
||||
* @param aCandidates [out] the candidate access key list.
|
||||
* the first item is most preferred.
|
||||
*/
|
||||
void GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
|
|
|
@ -449,6 +449,175 @@ WidgetKeyboardEvent::ShouldCauseKeypressEvents() const
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates)
|
||||
{
|
||||
for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
|
||||
uint32_t ch = aCandidates[i].mCharCode;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2)
|
||||
{
|
||||
return aChar1 == aChar2 ||
|
||||
(IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
|
||||
ToLowerCase(static_cast<char16_t>(aChar1)) ==
|
||||
ToLowerCase(static_cast<char16_t>(aChar2)));
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCaseChangeableChar(uint32_t aChar)
|
||||
{
|
||||
return IS_IN_BMP(aChar) &&
|
||||
ToLowerCase(static_cast<char16_t>(aChar)) !=
|
||||
ToUpperCase(static_cast<char16_t>(aChar));
|
||||
}
|
||||
|
||||
void
|
||||
WidgetKeyboardEvent::GetShortcutKeyCandidates(
|
||||
ShortcutKeyCandidateArray& aCandidates)
|
||||
{
|
||||
MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
|
||||
|
||||
if (mMessage != eKeyPress) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ShortcutKeyCandidate::mCharCode is a candidate charCode.
|
||||
// ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
|
||||
// execute a command with/without shift key state. If this is TRUE, the
|
||||
// shifted key state should be ignored. Otherwise, don't ignore the state.
|
||||
// the priority of the charCodes are (shift key is not pressed):
|
||||
// 0: charCode/false,
|
||||
// 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
|
||||
// the priority of the charCodes are (shift key is pressed):
|
||||
// 0: charCode/false,
|
||||
// 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
|
||||
// 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
|
||||
if (charCode) {
|
||||
ShortcutKeyCandidate key(charCode, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
|
||||
uint32_t len = alternativeCharCodes.Length();
|
||||
if (!IsShift()) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uint32_t ch = alternativeCharCodes[i].mUnshiftedCharCode;
|
||||
if (!ch || ch == charCode) {
|
||||
continue;
|
||||
}
|
||||
ShortcutKeyCandidate key(ch, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
// If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
|
||||
// this keyboard layout is AZERTY or similar layout, probably.
|
||||
// In this case, Accel+[0-9] should be accessible without shift key.
|
||||
// However, the priority should be lowest.
|
||||
if (!HasASCIIDigit(aCandidates)) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uint32_t ch = alternativeCharCodes[i].mShiftedCharCode;
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
ShortcutKeyCandidate key(ch, false);
|
||||
aCandidates.AppendElement(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uint32_t ch = alternativeCharCodes[i].mShiftedCharCode;
|
||||
if (!ch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch != charCode) {
|
||||
ShortcutKeyCandidate key(ch, false);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
|
||||
// If the char is an alphabet, the shift key state should not be
|
||||
// ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
|
||||
|
||||
// And checking the charCode is same as unshiftedCharCode too.
|
||||
// E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
|
||||
uint32_t unshiftCh = alternativeCharCodes[i].mUnshiftedCharCode;
|
||||
if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// On the Hebrew keyboard layout on Windows, the unshifted char is a
|
||||
// localized character but the shifted char is a Latin alphabet,
|
||||
// then, we should not execute without the shift state. See bug 433192.
|
||||
if (IsCaseChangeableChar(ch)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Setting the alternative charCode candidates for retry without shift
|
||||
// key state only when the shift key is pressed.
|
||||
ShortcutKeyCandidate key(ch, true);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for "Space" key. With some keyboard layouts, "Space" with
|
||||
// or without Shift key causes non-ASCII space. For such keyboard layouts,
|
||||
// we should guarantee that the key press works as an ASCII white space key
|
||||
// press.
|
||||
if (mCodeNameIndex == CODE_NAME_INDEX_Space &&
|
||||
charCode != static_cast<uint32_t>(' ')) {
|
||||
ShortcutKeyCandidate spaceKey(static_cast<uint32_t>(' '), false);
|
||||
aCandidates.AppendElement(spaceKey);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WidgetKeyboardEvent::GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates)
|
||||
{
|
||||
MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
|
||||
|
||||
// return the lower cased charCode candidates for access keys.
|
||||
// the priority of the charCodes are:
|
||||
// 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
|
||||
// 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
|
||||
if (charCode) {
|
||||
uint32_t ch = charCode;
|
||||
if (IS_IN_BMP(ch)) {
|
||||
ch = ToLowerCase(static_cast<char16_t>(ch));
|
||||
}
|
||||
aCandidates.AppendElement(ch);
|
||||
}
|
||||
for (uint32_t i = 0; i < alternativeCharCodes.Length(); ++i) {
|
||||
uint32_t ch[2] =
|
||||
{ alternativeCharCodes[i].mUnshiftedCharCode,
|
||||
alternativeCharCodes[i].mShiftedCharCode };
|
||||
for (uint32_t j = 0; j < 2; ++j) {
|
||||
if (!ch[j]) {
|
||||
continue;
|
||||
}
|
||||
if (IS_IN_BMP(ch[j])) {
|
||||
ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
|
||||
}
|
||||
// Don't append the charCode that was already appended.
|
||||
if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
|
||||
aCandidates.AppendElement(ch[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Special case for "Space" key. With some keyboard layouts, "Space" with
|
||||
// or without Shift key causes non-ASCII space. For such keyboard layouts,
|
||||
// we should guarantee that the key press works as an ASCII white space key
|
||||
// press.
|
||||
if (mCodeNameIndex == CODE_NAME_INDEX_Space &&
|
||||
charCode != static_cast<uint32_t>(' ')) {
|
||||
aCandidates.AppendElement(static_cast<uint32_t>(' '));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
WidgetKeyboardEvent::Shutdown()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче