зеркало из https://github.com/mozilla/pjs.git
Bug 359638 accesskeys are incorrectly shifted again (i.e. accesskey=. is broken) and also for b=398264, b=401086, b=414130, b=427797, b=427932, b=427995 r=karlt+ere+josh, sr=roc, a1.9=mconnor
This commit is contained in:
Родитель
8145c55c2b
Коммит
f0d97b8c55
|
@ -57,6 +57,7 @@
|
|||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
|
||||
|
||||
|
@ -124,6 +125,15 @@ struct EventNameMapping {
|
|||
PRInt32 mType;
|
||||
};
|
||||
|
||||
struct nsShortcutCandidate {
|
||||
nsShortcutCandidate(PRUint32 aCharCode, PRBool aIgnoreShift) :
|
||||
mCharCode(aCharCode), mIgnoreShift(aIgnoreShift)
|
||||
{
|
||||
}
|
||||
PRUint32 mCharCode;
|
||||
PRBool mIgnoreShift;
|
||||
};
|
||||
|
||||
class nsContentUtils
|
||||
{
|
||||
public:
|
||||
|
@ -1158,6 +1168,26 @@ public:
|
|||
nsNativeKeyEvent* aNativeEvent,
|
||||
PRBool aGetCharCode);
|
||||
|
||||
/**
|
||||
* Get the candidates for accelkeys for aDOMEvent.
|
||||
*
|
||||
* @param aDOMEvent [in] the input event for accelkey handling.
|
||||
* @param aCandidates [out] the candidate shortcut key combination list.
|
||||
* the first item is most preferred.
|
||||
*/
|
||||
static void GetAccelKeyCandidates(nsIDOMEvent* aDOMEvent,
|
||||
nsTArray<nsShortcutCandidate>& aCandidates);
|
||||
|
||||
/**
|
||||
* Get the candidates for accesskeys for aDOMEvent.
|
||||
*
|
||||
* @param aNativeKeyEvent [in] the input event for accesskey handling.
|
||||
* @param aCandidates [out] the candidate access key list.
|
||||
* the first item is most preferred.
|
||||
*/
|
||||
static void GetAccessKeyCandidates(nsKeyEvent* aNativeKeyEvent,
|
||||
nsTArray<PRUint32>& aCandidates);
|
||||
|
||||
/**
|
||||
* Hide any XUL popups associated with aDocument, including any documents
|
||||
* displayed in child frames.
|
||||
|
|
|
@ -3999,6 +3999,124 @@ nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMEvent* aDOMEvent,
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::GetAccelKeyCandidates(nsIDOMEvent* aDOMEvent,
|
||||
nsTArray<nsShortcutCandidate>& aCandidates)
|
||||
{
|
||||
NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
|
||||
|
||||
nsAutoString eventType;
|
||||
aDOMEvent->GetType(eventType);
|
||||
// Don't process if aDOMEvent is not a keypress event.
|
||||
if (!eventType.EqualsLiteral("keypress"))
|
||||
return;
|
||||
|
||||
nsKeyEvent* nativeKeyEvent =
|
||||
static_cast<nsKeyEvent*>(GetNativeEvent(aDOMEvent));
|
||||
if (nativeKeyEvent) {
|
||||
// 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/PR_FALSE,
|
||||
// 1: unshiftedCharCodes[0]/PR_FALSE, 2: unshiftedCharCodes[1]/PR_FALSE...
|
||||
// the priority of the charCodes are (shift key is pressed):
|
||||
// 0: charCode/PR_FALSE,
|
||||
// 1: shiftedCharCodes[0]/PR_FALSE, 2: shiftedCharCodes[0]/PR_TRUE,
|
||||
// 3: shiftedCharCodes[1]/PR_FALSE, 4: shiftedCharCodes[1]/PR_TRUE...
|
||||
if (nativeKeyEvent->charCode) {
|
||||
nsShortcutCandidate key(nativeKeyEvent->charCode, PR_FALSE);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
|
||||
if (!nativeKeyEvent->isShift) {
|
||||
for (PRUint32 i = 0;
|
||||
i < nativeKeyEvent->alternativeCharCodes.Length(); ++i) {
|
||||
PRUint32 ch =
|
||||
nativeKeyEvent->alternativeCharCodes[0].mUnshiftedCharCode;
|
||||
if (!ch || ch == nativeKeyEvent->charCode)
|
||||
continue;
|
||||
|
||||
nsShortcutCandidate key(ch, PR_FALSE);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
} else {
|
||||
for (PRUint32 i = 0;
|
||||
i < nativeKeyEvent->alternativeCharCodes.Length(); ++i) {
|
||||
PRUint32 ch = nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
|
||||
if (!ch)
|
||||
continue;
|
||||
|
||||
if (ch != nativeKeyEvent->charCode) {
|
||||
nsShortcutCandidate key(ch, PR_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.
|
||||
PRUint32 unshiftCh =
|
||||
nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
|
||||
if (ch == unshiftCh ||
|
||||
(IS_IN_BMP(ch) && IS_IN_BMP(unshiftCh) &&
|
||||
ToLowerCase(PRUnichar(ch)) == ToLowerCase(PRUnichar(unshiftCh))))
|
||||
continue;
|
||||
|
||||
// Setting the alternative charCode candidates for retry without shift
|
||||
// key state only when the shift key is pressed.
|
||||
nsShortcutCandidate key(ch, PR_TRUE);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aDOMEvent));
|
||||
PRUint32 charCode;
|
||||
key->GetCharCode(&charCode);
|
||||
if (charCode) {
|
||||
nsShortcutCandidate key(charCode, PR_FALSE);
|
||||
aCandidates.AppendElement(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::GetAccessKeyCandidates(nsKeyEvent* aNativeKeyEvent,
|
||||
nsTArray<PRUint32>& 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) {
|
||||
PRUint32 ch = aNativeKeyEvent->charCode;
|
||||
if (IS_IN_BMP(ch))
|
||||
ch = ToLowerCase(PRUnichar(ch));
|
||||
aCandidates.AppendElement(ch);
|
||||
}
|
||||
for (PRUint32 i = 0;
|
||||
i < aNativeKeyEvent->alternativeCharCodes.Length(); ++i) {
|
||||
PRUint32 ch[2] =
|
||||
{ aNativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode,
|
||||
aNativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode };
|
||||
for (PRUint32 j = 0; j < 2; ++j) {
|
||||
if (!ch[j])
|
||||
continue;
|
||||
if (IS_IN_BMP(ch[j]))
|
||||
ch[j] = ToLowerCase(PRUnichar(ch[j]));
|
||||
// Don't append the charCode that was already appended.
|
||||
if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex)
|
||||
aCandidates.AppendElement(ch[j]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsContentUtils::AddScriptBlocker()
|
||||
|
|
|
@ -1441,7 +1441,7 @@ GetAccessModifierMask(nsISupports* aDocShell)
|
|||
}
|
||||
|
||||
static PRBool
|
||||
IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsString& aKey)
|
||||
IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
|
||||
{
|
||||
if (!aFrame)
|
||||
return PR_FALSE;
|
||||
|
@ -1465,6 +1465,45 @@ IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsString& aKey)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEventStateManager::ExecuteAccessKey(nsTArray<PRUint32>& aAccessCharCodes,
|
||||
PRBool aIsTrustedEvent)
|
||||
{
|
||||
PRInt32 count, start = -1;
|
||||
if (mCurrentFocus) {
|
||||
start = mAccessKeys.IndexOf(mCurrentFocus);
|
||||
if (start == -1 && mCurrentFocus->GetBindingParent())
|
||||
start = mAccessKeys.IndexOf(mCurrentFocus->GetBindingParent());
|
||||
}
|
||||
nsIContent *content;
|
||||
nsIFrame *frame;
|
||||
PRInt32 length = mAccessKeys.Count();
|
||||
for (PRUint32 i = 0; i < aAccessCharCodes.Length(); ++i) {
|
||||
PRUint32 ch = aAccessCharCodes[i];
|
||||
nsAutoString accessKey;
|
||||
AppendUCS4ToUTF16(ch, accessKey);
|
||||
for (count = 1; count <= length; ++count) {
|
||||
content = mAccessKeys[(start + count) % length];
|
||||
frame = mPresContext->PresShell()->GetPrimaryFrameFor(content);
|
||||
if (IsAccessKeyTarget(content, frame, accessKey)) {
|
||||
PRBool shouldActivate = sKeyCausesActivation;
|
||||
while (shouldActivate && ++count <= length) {
|
||||
nsIContent *oc = mAccessKeys[(start + count) % length];
|
||||
nsIFrame *of = mPresContext->PresShell()->GetPrimaryFrameFor(oc);
|
||||
if (IsAccessKeyTarget(oc, of, accessKey))
|
||||
shouldActivate = PR_FALSE;
|
||||
}
|
||||
if (shouldActivate)
|
||||
content->PerformAccesskey(shouldActivate, aIsTrustedEvent);
|
||||
else if (frame && frame->IsFocusable())
|
||||
ChangeFocusWith(content, eEventFocusedByKey);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsEventStateManager::HandleAccessKey(nsPresContext* aPresContext,
|
||||
nsKeyEvent *aEvent,
|
||||
|
@ -1476,37 +1515,15 @@ nsEventStateManager::HandleAccessKey(nsPresContext* aPresContext,
|
|||
nsCOMPtr<nsISupports> pcContainer = aPresContext->GetContainer();
|
||||
|
||||
// Alt or other accesskey modifier is down, we may need to do an accesskey
|
||||
PRInt32 length = mAccessKeys.Count();
|
||||
if (length > 0 && aModifierMask == GetAccessModifierMask(pcContainer)) {
|
||||
if (mAccessKeys.Count() > 0 &&
|
||||
aModifierMask == GetAccessModifierMask(pcContainer)) {
|
||||
// Someone registered an accesskey. Find and activate it.
|
||||
nsAutoString accKey(aEvent->charCode);
|
||||
PRInt32 count, start = -1;
|
||||
if (mCurrentFocus) {
|
||||
start = mAccessKeys.IndexOf(mCurrentFocus);
|
||||
if (start == -1 && mCurrentFocus->GetBindingParent())
|
||||
start = mAccessKeys.IndexOf(mCurrentFocus->GetBindingParent());
|
||||
}
|
||||
nsIContent *content;
|
||||
nsIFrame *frame;
|
||||
for (count = 1; count <= length; ++count) {
|
||||
content = mAccessKeys[(start + count) % length];
|
||||
frame = mPresContext->PresShell()->GetPrimaryFrameFor(content);
|
||||
if (IsAccessKeyTarget(content, frame, accKey)) {
|
||||
PRBool shouldActivate = sKeyCausesActivation;
|
||||
while (shouldActivate && ++count <= length) {
|
||||
nsIContent *oc = mAccessKeys[(start + count) % length];
|
||||
nsIFrame *of = mPresContext->PresShell()->GetPrimaryFrameFor(oc);
|
||||
if (IsAccessKeyTarget(oc, of, accKey))
|
||||
shouldActivate = PR_FALSE;
|
||||
}
|
||||
if (shouldActivate)
|
||||
content->PerformAccesskey(shouldActivate,
|
||||
NS_IS_TRUSTED_EVENT(aEvent));
|
||||
else if (frame && frame->IsFocusable())
|
||||
ChangeFocusWith(content, eEventFocusedByKey);
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
break;
|
||||
}
|
||||
PRBool isTrusted = NS_IS_TRUSTED_EVENT(aEvent);
|
||||
nsAutoTArray<PRUint32, 10> accessCharCodes;
|
||||
nsContentUtils::GetAccessKeyCandidates(aEvent, accessCharCodes);
|
||||
if (ExecuteAccessKey(accessCharCodes, isTrusted)) {
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,9 @@ protected:
|
|||
ProcessingAccessKeyState aAccessKeyState,
|
||||
PRInt32 aModifierMask);
|
||||
|
||||
PRBool ExecuteAccessKey(nsTArray<PRUint32>& aAccessCharCodes,
|
||||
PRBool aIsTrustedEvent);
|
||||
|
||||
//---------------------------------------------
|
||||
// DocShell Focus Traversal Methods
|
||||
//---------------------------------------------
|
||||
|
|
|
@ -49,7 +49,9 @@
|
|||
#include "nsGkAtoms.h"
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
nsXBLEventHandler::nsXBLEventHandler(nsXBLPrototypeHandler* aHandler)
|
||||
: mProtoHandler(aHandler)
|
||||
|
@ -119,6 +121,36 @@ nsXBLKeyEventHandler::~nsXBLKeyEventHandler()
|
|||
|
||||
NS_IMPL_ISUPPORTS1(nsXBLKeyEventHandler, nsIDOMEventListener)
|
||||
|
||||
PRBool
|
||||
nsXBLKeyEventHandler::ExecuteMatchedHandlers(nsIDOMKeyEvent* aKeyEvent,
|
||||
PRUint32 aCharCode,
|
||||
PRBool aIgnoreShiftKey)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aKeyEvent);
|
||||
PRBool trustedEvent = PR_FALSE;
|
||||
if (domNSEvent)
|
||||
domNSEvent->GetIsTrusted(&trustedEvent);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aKeyEvent->GetCurrentTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsPIDOMEventTarget> piTarget = do_QueryInterface(target);
|
||||
|
||||
PRBool executed = PR_FALSE;
|
||||
for (PRUint32 i = 0; i < mProtoHandlers.Count(); ++i) {
|
||||
nsXBLPrototypeHandler* handler = static_cast<nsXBLPrototypeHandler*>
|
||||
(mProtoHandlers[i]);
|
||||
PRBool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
|
||||
if ((trustedEvent ||
|
||||
(hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
|
||||
(!hasAllowUntrustedAttr && !mIsBoundToChrome)) &&
|
||||
handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreShiftKey)) {
|
||||
handler->ExecuteHandler(piTarget, aKeyEvent);
|
||||
executed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
return executed;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
@ -133,31 +165,21 @@ nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetCurrentTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsPIDOMEventTarget> piTarget = do_QueryInterface(target);
|
||||
|
||||
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
|
||||
|
||||
nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aEvent);
|
||||
PRBool trustedEvent = PR_FALSE;
|
||||
if (domNSEvent) {
|
||||
domNSEvent->GetIsTrusted(&trustedEvent);
|
||||
nsAutoTArray<nsShortcutCandidate, 10> accessKeys;
|
||||
nsContentUtils::GetAccelKeyCandidates(aEvent, accessKeys);
|
||||
|
||||
if (accessKeys.IsEmpty()) {
|
||||
ExecuteMatchedHandlers(key, 0, PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsXBLPrototypeHandler* handler = static_cast<nsXBLPrototypeHandler*>
|
||||
(mProtoHandlers[i]);
|
||||
PRBool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
|
||||
if ((trustedEvent ||
|
||||
(hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
|
||||
(!hasAllowUntrustedAttr && !mIsBoundToChrome)) &&
|
||||
handler->KeyEventMatched(key)) {
|
||||
handler->ExecuteHandler(piTarget, aEvent);
|
||||
}
|
||||
for (PRUint32 i = 0; i < accessKeys.Length(); ++i) {
|
||||
if (ExecuteMatchedHandlers(key, accessKeys[i].mCharCode,
|
||||
accessKeys[i].mIgnoreShift))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
class nsIAtom;
|
||||
class nsIContent;
|
||||
class nsIDOM3EventTarget;
|
||||
class nsIDOMKeyEvent;
|
||||
class nsPIDOMEventTarget;
|
||||
class nsXBLPrototypeHandler;
|
||||
|
||||
|
@ -121,6 +122,8 @@ public:
|
|||
}
|
||||
private:
|
||||
nsXBLKeyEventHandler();
|
||||
PRBool ExecuteMatchedHandlers(nsIDOMKeyEvent* aEvent, PRUint32 aCharCode,
|
||||
PRBool aIgnoreShiftKey);
|
||||
|
||||
nsVoidArray mProtoHandlers;
|
||||
nsCOMPtr<nsIAtom> mEventType;
|
||||
|
|
|
@ -596,7 +596,9 @@ nsXBLPrototypeHandler::GetController(nsPIDOMEventTarget* aTarget)
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
|
||||
nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent,
|
||||
PRUint32 aCharCode,
|
||||
PRBool aIgnoreShiftKey)
|
||||
{
|
||||
if (mDetail == -1)
|
||||
return PR_TRUE; // No filters set up. It's generic.
|
||||
|
@ -605,8 +607,12 @@ nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
|
|||
PRUint32 code;
|
||||
|
||||
if (mMisc) {
|
||||
aKeyEvent->GetCharCode(&code);
|
||||
code = ToLowerCase(PRUnichar(code));
|
||||
if (aCharCode)
|
||||
code = aCharCode;
|
||||
else
|
||||
aKeyEvent->GetCharCode(&code);
|
||||
if (IS_IN_BMP(code))
|
||||
code = ToLowerCase(PRUnichar(code));
|
||||
}
|
||||
else
|
||||
aKeyEvent->GetKeyCode(&code);
|
||||
|
@ -614,7 +620,7 @@ nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
|
|||
if (code != PRUint32(mDetail))
|
||||
return PR_FALSE;
|
||||
|
||||
return ModifiersMatchMask(aKeyEvent);
|
||||
return ModifiersMatchMask(aKeyEvent, aIgnoreShiftKey);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -992,7 +998,8 @@ nsXBLPrototypeHandler::ReportKeyConflict(const PRUnichar* aKey, const PRUnichar*
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent)
|
||||
nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent,
|
||||
PRBool aIgnoreShiftKey)
|
||||
{
|
||||
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
|
||||
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
|
||||
|
@ -1004,7 +1011,7 @@ nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mKeyMask & cShiftMask) {
|
||||
if (mKeyMask & cShiftMask && !aIgnoreShiftKey) {
|
||||
key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
|
||||
if (keyPresent != ((mKeyMask & cShift) != 0))
|
||||
return PR_FALSE;
|
||||
|
|
|
@ -91,14 +91,19 @@ public:
|
|||
|
||||
~nsXBLPrototypeHandler();
|
||||
|
||||
PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
|
||||
// if aCharCode is not zero, it is used instead of the charCode of aKeyEvent.
|
||||
PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent,
|
||||
PRUint32 aCharCode = 0,
|
||||
PRBool aIgnoreShiftKey = PR_FALSE);
|
||||
inline PRBool KeyEventMatched(nsIAtom* aEventType,
|
||||
nsIDOMKeyEvent* aEvent)
|
||||
nsIDOMKeyEvent* aEvent,
|
||||
PRUint32 aCharCode = 0,
|
||||
PRBool aIgnoreShiftKey = PR_FALSE)
|
||||
{
|
||||
if (aEventType != mEventName)
|
||||
return PR_FALSE;
|
||||
|
||||
return KeyEventMatched(aEvent);
|
||||
return KeyEventMatched(aEvent, aCharCode, aIgnoreShiftKey);
|
||||
}
|
||||
|
||||
PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
|
||||
|
@ -171,7 +176,8 @@ protected:
|
|||
|
||||
void ReportKeyConflict(const PRUnichar* aKey, const PRUnichar* aModifiers, nsIContent* aElement, const char *aMessageName);
|
||||
void GetEventType(nsAString& type);
|
||||
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent);
|
||||
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent,
|
||||
PRBool aIgnoreShiftKey = PR_FALSE);
|
||||
nsresult DispatchXBLCommand(nsPIDOMEventTarget* aTarget, nsIDOMEvent* aEvent);
|
||||
nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
|
||||
nsresult EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
static nsINativeKeyBindings *sNativeEditorBindings = nsnull;
|
||||
|
||||
|
@ -216,6 +217,16 @@ BuildHandlerChain(nsIContent* aContent, nsXBLPrototypeHandler** aResult)
|
|||
nsIContent *key = aContent->GetChildAt(j);
|
||||
|
||||
if (key->NodeInfo()->Equals(nsGkAtoms::key, kNameSpaceID_XUL)) {
|
||||
// Check whether the key element has empty value at key/char attribute.
|
||||
// Such element is used by localizers for alternative shortcut key
|
||||
// definition on the locale. See bug 426501.
|
||||
nsAutoString valKey, valChar;
|
||||
PRBool attrExists =
|
||||
key->GetAttr(kNameSpaceID_None, nsGkAtoms::key, valKey) ||
|
||||
key->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, valChar);
|
||||
if (attrExists && valKey.IsEmpty() && valChar.IsEmpty())
|
||||
continue;
|
||||
|
||||
nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(key);
|
||||
|
||||
if (!handler)
|
||||
|
@ -405,11 +416,13 @@ nsresult nsXBLWindowKeyHandler::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
//
|
||||
PRBool
|
||||
nsXBLWindowKeyHandler::EventMatched(nsXBLPrototypeHandler* inHandler,
|
||||
nsIAtom* inEventType, nsIDOMEvent* inEvent)
|
||||
nsIAtom* inEventType, nsIDOMEvent* inEvent,
|
||||
PRUint32 aCharCode, PRBool aIgnoreShiftKey)
|
||||
{
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(inEvent));
|
||||
if (keyEvent)
|
||||
return inHandler->KeyEventMatched(inEventType, keyEvent);
|
||||
return inHandler->KeyEventMatched(inEventType, keyEvent, aCharCode,
|
||||
aIgnoreShiftKey);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -458,7 +471,7 @@ nsXBLWindowKeyHandler::IsEditor()
|
|||
}
|
||||
|
||||
//
|
||||
// WalkHandlersInternal
|
||||
// WalkHandlersInternal and WalkHandlersAndExecute
|
||||
//
|
||||
// Given a particular DOM event and a pointer to the first handler in the list,
|
||||
// scan through the list to find something to handle the event and then make it
|
||||
|
@ -468,10 +481,34 @@ nsresult
|
|||
nsXBLWindowKeyHandler::WalkHandlersInternal(nsIDOMEvent* aEvent,
|
||||
nsIAtom* aEventType,
|
||||
nsXBLPrototypeHandler* aHandler)
|
||||
{
|
||||
nsAutoTArray<nsShortcutCandidate, 10> accessKeys;
|
||||
nsContentUtils::GetAccelKeyCandidates(aEvent, accessKeys);
|
||||
|
||||
if (accessKeys.IsEmpty()) {
|
||||
WalkHandlersAndExecute(aEvent, aEventType, aHandler, 0, PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < accessKeys.Length(); ++i) {
|
||||
nsShortcutCandidate &key = accessKeys[i];
|
||||
if (WalkHandlersAndExecute(aEvent, aEventType, aHandler,
|
||||
key.mCharCode, key.mIgnoreShift))
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXBLWindowKeyHandler::WalkHandlersAndExecute(nsIDOMEvent* aEvent,
|
||||
nsIAtom* aEventType,
|
||||
nsXBLPrototypeHandler* aHandler,
|
||||
PRUint32 aCharCode,
|
||||
PRBool aIgnoreShiftKey)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
|
||||
|
||||
|
||||
// Try all of the handlers until we find one that matches the event.
|
||||
for (nsXBLPrototypeHandler *currHandler = aHandler; currHandler;
|
||||
currHandler = currHandler->GetNextHandler()) {
|
||||
|
@ -482,7 +519,8 @@ nsXBLWindowKeyHandler::WalkHandlersInternal(nsIDOMEvent* aEvent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!EventMatched(currHandler, aEventType, aEvent))
|
||||
if (!EventMatched(currHandler, aEventType, aEvent,
|
||||
aCharCode, aIgnoreShiftKey))
|
||||
continue; // try the next one
|
||||
|
||||
// Before executing this handler, check that it's not disabled,
|
||||
|
@ -541,11 +579,11 @@ nsXBLWindowKeyHandler::WalkHandlersInternal(nsIDOMEvent* aEvent,
|
|||
|
||||
rv = currHandler->ExecuteHandler(piTarget, aEvent);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return NS_OK;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMElement>
|
||||
|
|
|
@ -80,13 +80,19 @@ protected:
|
|||
nsIAtom* aEventType,
|
||||
nsXBLPrototypeHandler* aHandler);
|
||||
|
||||
// walk the handlers for aEvent, aCharCode and aIgnoreShiftKey
|
||||
PRBool WalkHandlersAndExecute(nsIDOMEvent* aEvent, nsIAtom* aEventType,
|
||||
nsXBLPrototypeHandler* aHandler,
|
||||
PRUint32 aCharCode, PRBool aIgnoreShiftKey);
|
||||
|
||||
// lazily load the handlers. Overridden to handle being attached
|
||||
// to a particular element rather than the document
|
||||
nsresult EnsureHandlers(PRBool *aIsEditor);
|
||||
|
||||
// check if the given handler cares about the given key event
|
||||
PRBool EventMatched(nsXBLPrototypeHandler* inHandler, nsIAtom* inEventType,
|
||||
nsIDOMEvent* inEvent);
|
||||
nsIDOMEvent* inEvent, PRUint32 aCharCode,
|
||||
PRBool aIgnoreShiftKey);
|
||||
|
||||
// are we working with editor or browser?
|
||||
PRBool IsEditor() ;
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
#include "nsISound.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#endif
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
|
||||
//
|
||||
|
@ -209,8 +211,17 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
{
|
||||
PRUint32 charCode;
|
||||
aKeyEvent->GetCharCode(&charCode);
|
||||
if (!charCode) // no character was pressed so just return
|
||||
return nsnull;
|
||||
|
||||
nsAutoTArray<PRUint32, 10> accessKeys;
|
||||
nsEvent* nativeEvent = nsContentUtils::GetNativeEvent(aKeyEvent);
|
||||
nsKeyEvent* nativeKeyEvent = static_cast<nsKeyEvent*>(nativeEvent);
|
||||
if (nativeKeyEvent)
|
||||
nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, accessKeys);
|
||||
if (accessKeys.IsEmpty() && charCode)
|
||||
accessKeys.AppendElement(charCode);
|
||||
|
||||
if (accessKeys.IsEmpty())
|
||||
return nsnull; // no character was pressed so just return
|
||||
|
||||
// Enumerate over our list of frames.
|
||||
nsIFrame* immediateParent = nsnull;
|
||||
|
@ -218,29 +229,39 @@ nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
|
|||
if (!immediateParent)
|
||||
immediateParent = this;
|
||||
|
||||
// Find a most preferred accesskey which should be returned.
|
||||
nsIFrame* foundMenu = nsnull;
|
||||
PRUint32 foundIndex = accessKeys.NoIndex;
|
||||
nsIFrame* currFrame = immediateParent->GetFirstChild(nsnull);
|
||||
|
||||
while (currFrame) {
|
||||
nsIContent* current = currFrame->GetContent();
|
||||
|
||||
|
||||
// See if it's a menu item.
|
||||
if (nsXULPopupManager::IsValidMenuItem(PresContext(), current, PR_FALSE)) {
|
||||
// Get the shortcut attribute.
|
||||
nsAutoString shortcutKey;
|
||||
current->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, shortcutKey);
|
||||
if (!shortcutKey.IsEmpty()) {
|
||||
// We've got something.
|
||||
PRUnichar letter = PRUnichar(charCode); // throw away the high-zero-fill
|
||||
if ( shortcutKey.Equals(Substring(&letter, &letter+1),
|
||||
nsCaseInsensitiveStringComparator()) ) {
|
||||
// We match!
|
||||
return (currFrame->GetType() == nsGkAtoms::menuFrame) ?
|
||||
static_cast<nsMenuFrame *>(currFrame) : nsnull;
|
||||
ToLowerCase(shortcutKey);
|
||||
nsAutoString::const_iterator start, end;
|
||||
shortcutKey.BeginReading(start);
|
||||
shortcutKey.EndReading(end);
|
||||
PRUint32 ch = UTF16CharEnumerator::NextChar(start, end);
|
||||
PRUint32 index = accessKeys.IndexOf(ch);
|
||||
if (index != accessKeys.NoIndex &&
|
||||
(foundIndex == kNotFound || index < foundIndex)) {
|
||||
foundMenu = currFrame;
|
||||
foundIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
currFrame = currFrame->GetNextSibling();
|
||||
}
|
||||
if (foundMenu) {
|
||||
return (foundMenu->GetType() == nsGkAtoms::menuFrame) ?
|
||||
static_cast<nsMenuFrame *>(foundMenu) : nsnull;
|
||||
}
|
||||
|
||||
// didn't find a matching menu item
|
||||
#ifdef XP_WIN
|
||||
|
|
|
@ -234,14 +234,22 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
keyEvent->GetKeyCode(&keyCode);
|
||||
keyEvent->GetCharCode(&charCode);
|
||||
|
||||
PRBool hasAccessKeyCandidates = charCode != 0;
|
||||
if (!hasAccessKeyCandidates) {
|
||||
nsEvent* nativeEvent = nsContentUtils::GetNativeEvent(aKeyEvent);
|
||||
nsKeyEvent* nativeKeyEvent = static_cast<nsKeyEvent*>(nativeEvent);
|
||||
if (nativeKeyEvent) {
|
||||
nsAutoTArray<PRUint32, 10> keys;
|
||||
nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, keys);
|
||||
hasAccessKeyCandidates = !keys.IsEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the access key flag unless we are pressing the access key.
|
||||
if (keyCode != (PRUint32)mAccessKey)
|
||||
mAccessKeyDown = PR_FALSE;
|
||||
|
||||
// If charCode == 0, then it is not a printable character.
|
||||
// Don't attempt to handle accesskey for non-printable characters.
|
||||
if (IsAccessKeyPressed(keyEvent) && charCode)
|
||||
{
|
||||
if (IsAccessKeyPressed(keyEvent) && hasAccessKeyCandidates) {
|
||||
// Do shortcut navigation.
|
||||
// A letter was pressed. We want to see if a shortcut gets matched. If
|
||||
// so, we'll know the menu got activated.
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIRenderingContext;
|
||||
class nsIRegion;
|
||||
|
@ -700,6 +701,16 @@ public:
|
|||
* Keyboard event
|
||||
*/
|
||||
|
||||
struct nsAlternativeCharCode {
|
||||
nsAlternativeCharCode(PRUint32 aUnshiftedCharCode,
|
||||
PRUint32 aShiftedCharCode) :
|
||||
mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
|
||||
{
|
||||
}
|
||||
PRUint32 mUnshiftedCharCode;
|
||||
PRUint32 mShiftedCharCode;
|
||||
};
|
||||
|
||||
class nsKeyEvent : public nsInputEvent
|
||||
{
|
||||
public:
|
||||
|
@ -713,6 +724,9 @@ public:
|
|||
PRUint32 keyCode;
|
||||
/// OS translated Unicode char
|
||||
PRUint32 charCode;
|
||||
// OS translated Unicode chars which are used for accesskey and accelkey
|
||||
// handling. The handlers will try from first character to last character.
|
||||
nsTArray<nsAlternativeCharCode> alternativeCharCodes;
|
||||
// indicates whether the event signifies a printable character
|
||||
PRBool isChar;
|
||||
};
|
||||
|
|
|
@ -3879,17 +3879,73 @@ static PRBool IsNormalCharInputtingEvent(const nsKeyEvent& aEvent)
|
|||
outGeckoEvent->charCode = 0;
|
||||
outGeckoEvent->keyCode = 0; // not set for key press events
|
||||
|
||||
NSString* unmodifiedChars = [aKeyEvent charactersIgnoringModifiers];
|
||||
if ([unmodifiedChars length] > 0)
|
||||
outGeckoEvent->charCode = [unmodifiedChars characterAtIndex:0];
|
||||
NSString* chars = [aKeyEvent characters];
|
||||
if ([chars length] > 0)
|
||||
outGeckoEvent->charCode = [chars characterAtIndex:0];
|
||||
|
||||
// convert control-modified charCode to raw charCode (with appropriate case)
|
||||
if (outGeckoEvent->isControl && outGeckoEvent->charCode <= 26)
|
||||
outGeckoEvent->charCode += (outGeckoEvent->isShift) ? ('A' - 1) : ('a' - 1);
|
||||
|
||||
// gecko also wants charCode to be in the appropriate case
|
||||
if (outGeckoEvent->isShift && (outGeckoEvent->charCode >= 'a' && outGeckoEvent->charCode <= 'z'))
|
||||
outGeckoEvent->charCode -= 32; // convert to uppercase
|
||||
// If Ctrl or Command is pressed, we should set shiftCharCode and
|
||||
// unshiftCharCode for accessKeys and accelKeys.
|
||||
if ((outGeckoEvent->isControl || outGeckoEvent->isMeta) &&
|
||||
!outGeckoEvent->isAlt) {
|
||||
SInt16 keyLayoutID =
|
||||
::GetScriptVariable(::GetScriptManagerVariable(smKeyScript),
|
||||
smScriptKeys);
|
||||
Handle handle = ::GetResource('uchr', keyLayoutID);
|
||||
PRUint32 unshiftedChar = 0;
|
||||
PRUint32 shiftedChar = 0;
|
||||
PRUint32 shiftedCmdChar = 0;
|
||||
if (handle) {
|
||||
UInt32 kbType = ::LMGetKbdType();
|
||||
UInt32 deadKeyState = 0;
|
||||
UniCharCount len;
|
||||
UniChar chars[1];
|
||||
OSStatus err;
|
||||
err = ::UCKeyTranslate((UCKeyboardLayout*)*handle,
|
||||
[aKeyEvent keyCode],
|
||||
kUCKeyActionDown, 0,
|
||||
kbType, 0, &deadKeyState, 1, &len, chars);
|
||||
if (noErr == err && len > 0)
|
||||
unshiftedChar = chars[0];
|
||||
deadKeyState = 0;
|
||||
err = ::UCKeyTranslate((UCKeyboardLayout*)*handle, [aKeyEvent keyCode],
|
||||
kUCKeyActionDown, shiftKey >> 8,
|
||||
kbType, 0, &deadKeyState, 1, &len, chars);
|
||||
if (noErr == err && len > 0)
|
||||
shiftedChar = chars[0];
|
||||
deadKeyState = 0;
|
||||
err = ::UCKeyTranslate((UCKeyboardLayout*)*handle, [aKeyEvent keyCode],
|
||||
kUCKeyActionDown, (cmdKey | shiftKey) >> 8,
|
||||
kbType, 0, &deadKeyState, 1, &len, chars);
|
||||
if (noErr == err && len > 0)
|
||||
shiftedCmdChar = chars[0];
|
||||
} else if (handle = (char**)::GetScriptManagerVariable(smKCHRCache)) {
|
||||
UInt32 state = 0;
|
||||
UInt32 keyCode = [aKeyEvent keyCode];
|
||||
unshiftedChar = ::KeyTranslate(handle, keyCode, &state) & charCodeMask;
|
||||
keyCode = [aKeyEvent keyCode] | shiftKey;
|
||||
shiftedChar = ::KeyTranslate(handle, keyCode, &state) & charCodeMask;
|
||||
keyCode = [aKeyEvent keyCode] | shiftKey | cmdKey;
|
||||
shiftedCmdChar = ::KeyTranslate(handle, keyCode, &state) & charCodeMask;
|
||||
}
|
||||
// If the current keyboad layout is switchable by Cmd key
|
||||
// (e.g., Dvorak-QWERTY layout), we should not append the alternative
|
||||
// char codes to unshiftedCharCodes and shiftedCharCodes.
|
||||
// Because then, the alternative char codes might execute wrong item.
|
||||
// Therefore, we should check whether the unshiftedChar and shiftedCmdChar
|
||||
// are same. Because Cmd+Shift+'foo' returns unshifted 'foo'. So, they
|
||||
// should be same for this case.
|
||||
// Note that we cannot support the combination of Cmd and Shift needed
|
||||
// char. (E.g., Cmd++ in US keyboard layout.)
|
||||
if ((unshiftedChar || shiftedChar) &&
|
||||
(!outGeckoEvent->isMeta || unshiftedChar == shiftedCmdChar)) {
|
||||
nsAlternativeCharCode altCharCodes(unshiftedChar, shiftedChar);
|
||||
outGeckoEvent->alternativeCharCodes.AppendElement(altCharCodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
NSString* characters = nil;
|
||||
|
|
|
@ -280,6 +280,47 @@ nsNativeKeyBindings::KeyPress(const nsNativeKeyEvent& aEvent,
|
|||
else
|
||||
keyCode = DOMKeyCodeToGdkKeyCode(aEvent.keyCode);
|
||||
|
||||
if (KeyPressInternal(aEvent, aCallback, aCallbackData, keyCode))
|
||||
return PR_TRUE;
|
||||
|
||||
nsKeyEvent *nativeKeyEvent = static_cast<nsKeyEvent*>(aEvent.nativeEvent);
|
||||
if (!nativeKeyEvent || nativeKeyEvent->eventStructType != NS_KEY_EVENT &&
|
||||
nativeKeyEvent->message != NS_KEY_PRESS)
|
||||
return PR_FALSE;
|
||||
|
||||
for (PRUint32 i = 0; i < nativeKeyEvent->alternativeCharCodes.Length(); ++i) {
|
||||
PRUint32 ch = nativeKeyEvent->isShift ?
|
||||
nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode :
|
||||
nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
|
||||
if (ch && ch != aEvent.charCode) {
|
||||
keyCode = gdk_unicode_to_keyval(ch);
|
||||
if (KeyPressInternal(aEvent, aCallback, aCallbackData, keyCode))
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* gtk_bindings_activate_event is preferable, but it has unresolved bug: http://bugzilla.gnome.org/show_bug.cgi?id=162726
|
||||
Also gtk_bindings_activate may work with some non-shortcuts operations (todo: check it)
|
||||
See bugs 411005 406407
|
||||
|
||||
Code, which should be used after fixing http://bugzilla.gnome.org/show_bug.cgi?id=162726:
|
||||
const nsGUIEvent *guiEvent = static_cast<nsGUIEvent*>(aEvent.nativeEvent);
|
||||
if (guiEvent &&
|
||||
(guiEvent->message == NS_KEY_PRESS || guiEvent->message == NS_KEY_UP || guiEvent->message == NS_KEY_DOWN) &&
|
||||
guiEvent->nativeMsg)
|
||||
gtk_bindings_activate_event(GTK_OBJECT(mNativeTarget),
|
||||
static_cast<GdkEventKey*>(guiEvent->nativeMsg));
|
||||
*/
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNativeKeyBindings::KeyPressInternal(const nsNativeKeyEvent& aEvent,
|
||||
DoCommandCallback aCallback,
|
||||
void *aCallbackData,
|
||||
PRUint32 aKeyCode)
|
||||
{
|
||||
int modifiers = 0;
|
||||
if (aEvent.altKey)
|
||||
modifiers |= GDK_MOD1_MASK;
|
||||
|
@ -295,20 +336,8 @@ nsNativeKeyBindings::KeyPress(const nsNativeKeyEvent& aEvent,
|
|||
gHandled = PR_FALSE;
|
||||
|
||||
gtk_bindings_activate(GTK_OBJECT(mNativeTarget),
|
||||
keyCode, GdkModifierType(modifiers));
|
||||
aKeyCode, GdkModifierType(modifiers));
|
||||
|
||||
/* gtk_bindings_activate_event is preferable, but it has unresolved bug: http://bugzilla.gnome.org/show_bug.cgi?id=162726
|
||||
Also gtk_bindings_activate may work with some non-shortcuts operations (todo: check it)
|
||||
See bugs 411005 406407
|
||||
|
||||
Code, which should be used after fixing http://bugzilla.gnome.org/show_bug.cgi?id=162726:
|
||||
const nsGUIEvent *guiEvent = static_cast<nsGUIEvent*>(aEvent.nativeEvent);
|
||||
if (guiEvent &&
|
||||
(guiEvent->message == NS_KEY_PRESS || guiEvent->message == NS_KEY_UP || guiEvent->message == NS_KEY_DOWN) &&
|
||||
guiEvent->nativeMsg)
|
||||
gtk_bindings_activate_event(GTK_OBJECT(mNativeTarget),
|
||||
static_cast<GdkEventKey*>(guiEvent->nativeMsg));
|
||||
*/
|
||||
gCurrentCallback = nsnull;
|
||||
gCurrentCallbackData = nsnull;
|
||||
|
||||
|
|
|
@ -93,6 +93,11 @@ public:
|
|||
private:
|
||||
~nsNativeKeyBindings() NS_HIDDEN;
|
||||
|
||||
PRBool KeyPressInternal(const nsNativeKeyEvent& aEvent,
|
||||
DoCommandCallback aCallback,
|
||||
void *aCallbackData,
|
||||
PRUint32 aKeyCode);
|
||||
|
||||
GtkWidget *mNativeTarget;
|
||||
};
|
||||
|
||||
|
|
|
@ -2276,14 +2276,6 @@ nsWindow::OnContainerFocusOutEvent(GtkWidget *aWidget, GdkEventFocus *aEvent)
|
|||
LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
|
||||
}
|
||||
|
||||
inline PRBool
|
||||
is_latin_shortcut_key(guint aKeyval)
|
||||
{
|
||||
return ((GDK_0 <= aKeyval && aKeyval <= GDK_9) ||
|
||||
(GDK_A <= aKeyval && aKeyval <= GDK_Z) ||
|
||||
(GDK_a <= aKeyval && aKeyval <= GDK_z));
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
|
||||
{
|
||||
|
@ -2293,6 +2285,45 @@ nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static PRUint32
|
||||
GetCharCodeFor(const GdkEventKey *aEvent, GdkModifierType aShiftState,
|
||||
gint aGroup)
|
||||
{
|
||||
guint keyval;
|
||||
if (gdk_keymap_translate_keyboard_state(NULL,
|
||||
aEvent->hardware_keycode,
|
||||
aShiftState, aGroup,
|
||||
&keyval, NULL, NULL, NULL)) {
|
||||
GdkEventKey tmpEvent = *aEvent;
|
||||
tmpEvent.state = guint(aShiftState);
|
||||
tmpEvent.keyval = keyval;
|
||||
tmpEvent.group = aGroup;
|
||||
return nsConvertCharCodeToUnicode(&tmpEvent);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint
|
||||
GetKeyLevel(GdkEventKey *aEvent)
|
||||
{
|
||||
gint level;
|
||||
if (!gdk_keymap_translate_keyboard_state(NULL,
|
||||
aEvent->hardware_keycode,
|
||||
GdkModifierType(aEvent->state),
|
||||
aEvent->group,
|
||||
NULL, NULL, &level, NULL))
|
||||
return -1;
|
||||
return level;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
IsBasicLatinLetterOrNumeral(PRUint32 aChar)
|
||||
{
|
||||
return (aChar >= 'a' && aChar <= 'z') ||
|
||||
(aChar >= 'A' && aChar <= 'Z') ||
|
||||
(aChar >= '0' && aChar <= '9');
|
||||
}
|
||||
|
||||
gboolean
|
||||
nsWindow::OnKeyPressEvent(GtkWidget *aWidget, GdkEventKey *aEvent)
|
||||
{
|
||||
|
@ -2382,91 +2413,60 @@ nsWindow::OnKeyPressEvent(GtkWidget *aWidget, GdkEventKey *aEvent)
|
|||
event.charCode = nsConvertCharCodeToUnicode(aEvent);
|
||||
if (event.charCode) {
|
||||
event.keyCode = 0;
|
||||
// if the control, meta, or alt key is down, then we should leave
|
||||
// the isShift flag alone (probably not a printable character)
|
||||
// if none of the other modifier keys are pressed then we need to
|
||||
// clear isShift so the character can be inserted in the editor
|
||||
|
||||
if (event.isControl || event.isAlt || event.isMeta) {
|
||||
GdkEventKey tmpEvent = *aEvent;
|
||||
|
||||
// Fix for bug 69230:
|
||||
// if modifier key is pressed and key pressed is not latin character,
|
||||
// we should try other keyboard layouts to find out correct latin
|
||||
// character corresponding to pressed key;
|
||||
// that way shortcuts like Ctrl+C will work no matter what
|
||||
// keyboard layout is selected
|
||||
// We don't try to fix up punctuation accelerators here,
|
||||
// because their location differs between latin layouts
|
||||
if (!is_latin_shortcut_key(event.charCode)) {
|
||||
// We have a non-latin char, try other keyboard groups
|
||||
GdkKeymapKey *keys;
|
||||
guint *keyvals;
|
||||
gint n_entries;
|
||||
PRUint32 latinCharCode;
|
||||
gint level;
|
||||
|
||||
if (gdk_keymap_translate_keyboard_state(NULL,
|
||||
tmpEvent.hardware_keycode,
|
||||
(GdkModifierType)tmpEvent.state,
|
||||
tmpEvent.group,
|
||||
NULL, NULL, &level, NULL)
|
||||
&& gdk_keymap_get_entries_for_keycode(NULL,
|
||||
tmpEvent.hardware_keycode,
|
||||
&keys, &keyvals,
|
||||
&n_entries)) {
|
||||
gint n;
|
||||
for (n=0; n<n_entries; n++) {
|
||||
if (keys[n].group == tmpEvent.group) {
|
||||
// Skip keys from the same group
|
||||
continue;
|
||||
}
|
||||
if (keys[n].level != level) {
|
||||
// Allow only same level keys
|
||||
continue;
|
||||
}
|
||||
if (is_latin_shortcut_key(keyvals[n])) {
|
||||
// Latin character found
|
||||
if (event.isShift)
|
||||
tmpEvent.keyval = gdk_keyval_to_upper(keyvals[n]);
|
||||
else
|
||||
tmpEvent.keyval = gdk_keyval_to_lower(keyvals[n]);
|
||||
tmpEvent.group = keys[n].group;
|
||||
latinCharCode = nsConvertCharCodeToUnicode(&tmpEvent);
|
||||
if (latinCharCode) {
|
||||
event.charCode = latinCharCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free(keys);
|
||||
g_free(keyvals);
|
||||
}
|
||||
gint level = GetKeyLevel(aEvent);
|
||||
if ((event.isControl || event.isAlt || event.isMeta) &&
|
||||
(level == 0 || level == 1)) {
|
||||
// We shold send both shifted char and unshifted char,
|
||||
// all keyboard layout users can use all keys.
|
||||
// Don't change event.charCode. On some keyboard layouts,
|
||||
// ctrl/alt/meta keys are used for inputting some characters.
|
||||
nsAlternativeCharCode altCharCodes(0, 0);
|
||||
// unshifted charcode of current keyboard layout.
|
||||
altCharCodes.mUnshiftedCharCode =
|
||||
GetCharCodeFor(aEvent, GdkModifierType(0), aEvent->group);
|
||||
PRBool isLatin = (altCharCodes.mUnshiftedCharCode <= 0xFF);
|
||||
// shifted charcode of current keyboard layout.
|
||||
altCharCodes.mShiftedCharCode =
|
||||
GetCharCodeFor(aEvent, GDK_SHIFT_MASK, aEvent->group);
|
||||
isLatin = isLatin && (altCharCodes.mShiftedCharCode <= 0xFF);
|
||||
if (altCharCodes.mUnshiftedCharCode ||
|
||||
altCharCodes.mShiftedCharCode) {
|
||||
event.alternativeCharCodes.AppendElement(altCharCodes);
|
||||
}
|
||||
|
||||
// make Ctrl+uppercase functional as same as Ctrl+lowercase
|
||||
// when Ctrl+uppercase(eg.Ctrl+C) is pressed,convert the charCode
|
||||
// from uppercase to lowercase(eg.Ctrl+c),so do Alt and Meta Key
|
||||
// It is hack code for bug 61355, there is same code snip for
|
||||
// Windows platform in widget/src/windows/nsWindow.cpp: See bug 16486
|
||||
// Note: if Shift is pressed at the same time, do not to_lower()
|
||||
// Because Ctrl+Shift has different function with Ctrl
|
||||
if (!event.isShift &&
|
||||
event.charCode >= GDK_A &&
|
||||
event.charCode <= GDK_Z)
|
||||
event.charCode = gdk_keyval_to_lower(event.charCode);
|
||||
|
||||
// Keep the characters unshifted for shortcuts and accesskeys and
|
||||
// make sure that numbers are always passed as such (among others:
|
||||
// bugs 50255 and 351310)
|
||||
if (!event.isControl && event.isShift &&
|
||||
(event.charCode < GDK_0 || event.charCode > GDK_9)) {
|
||||
GdkKeymapKey k = { tmpEvent.hardware_keycode, tmpEvent.group, 0 };
|
||||
tmpEvent.keyval = gdk_keymap_lookup_key(gdk_keymap_get_default(), &k);
|
||||
PRUint32 unshiftedCharCode = nsConvertCharCodeToUnicode(&tmpEvent);
|
||||
if (unshiftedCharCode)
|
||||
event.charCode = unshiftedCharCode;
|
||||
}
|
||||
if (!isLatin) {
|
||||
// Next, find latin inputtable keyboard layout.
|
||||
GdkKeymapKey *keys;
|
||||
gint count;
|
||||
gint minGroup = -1;
|
||||
if (gdk_keymap_get_entries_for_keyval(NULL, GDK_a,
|
||||
&keys, &count)) {
|
||||
// find the minimum number group for latin inputtable layout
|
||||
for (gint i = 0; i < count && minGroup != 0; ++i) {
|
||||
if (keys[i].level != 0 && keys[i].level != 1)
|
||||
continue;
|
||||
if (minGroup >= 0 && keys[i].group > minGroup)
|
||||
continue;
|
||||
minGroup = keys[i].group;
|
||||
}
|
||||
g_free(keys);
|
||||
}
|
||||
if (minGroup >= 0) {
|
||||
// unshifted charcode of found keyboard layout.
|
||||
PRUint32 ch =
|
||||
GetCharCodeFor(aEvent, GdkModifierType(0), minGroup);
|
||||
altCharCodes.mUnshiftedCharCode =
|
||||
IsBasicLatinLetterOrNumeral(ch) ? ch : 0;
|
||||
// shifted charcode of found keyboard layout.
|
||||
ch = GetCharCodeFor(aEvent, GDK_SHIFT_MASK, minGroup);
|
||||
altCharCodes.mShiftedCharCode =
|
||||
IsBasicLatinLetterOrNumeral(ch) ? ch : 0;
|
||||
if (altCharCodes.mUnshiftedCharCode ||
|
||||
altCharCodes.mShiftedCharCode) {
|
||||
event.alternativeCharCodes.AppendElement(altCharCodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -324,6 +324,30 @@ PRUint32 KeyboardLayout::GetUniChars (PRUint16* aUniChars, PRUint8* aShiftStates
|
|||
#endif
|
||||
}
|
||||
|
||||
PRUint32
|
||||
KeyboardLayout::GetUniCharsWithShiftState(PRUint8 aVirtualKey,
|
||||
PRUint8 aShiftStates,
|
||||
PRUint16* aUniChars,
|
||||
PRUint32 aMaxChars) const
|
||||
{
|
||||
#ifndef WINCE
|
||||
PRInt32 key = GetKeyIndex(aVirtualKey);
|
||||
if (key < 0)
|
||||
return 0;
|
||||
PRUint8 finalShiftState;
|
||||
PRUint16 uniChars[5];
|
||||
PRUint32 numOfBaseChars =
|
||||
mVirtualKeys[key].GetUniChars(aShiftStates, uniChars, &finalShiftState);
|
||||
PRUint32 chars = PR_MIN(numOfBaseChars, aMaxChars);
|
||||
|
||||
memcpy(aUniChars, uniChars, chars * sizeof (PRUint16));
|
||||
|
||||
return chars;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void KeyboardLayout::LoadLayout ()
|
||||
{
|
||||
#ifndef WINCE
|
||||
|
|
|
@ -180,6 +180,9 @@ public:
|
|||
void LoadLayout ();
|
||||
void OnKeyDown (PRUint8 aVirtualKey);
|
||||
PRUint32 GetUniChars (PRUint16* aUniChars, PRUint8* aShiftStates, PRUint32 aMaxChars) const;
|
||||
PRUint32 GetUniCharsWithShiftState(PRUint8 aVirtualKey, PRUint8 aShiftStates,
|
||||
PRUint16* aUniChars,
|
||||
PRUint32 aMaxChars) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3040,7 +3040,10 @@ UINT nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode)
|
|||
// OnKey
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode, UINT aVirtualCharCode,
|
||||
PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode,
|
||||
PRUint32 aUnshiftedCharCode,
|
||||
PRUint32 aShiftedCharCode,
|
||||
UINT aVirtualCharCode,
|
||||
LPARAM aKeyData, PRUint32 aFlags)
|
||||
{
|
||||
nsKeyEvent event(PR_TRUE, aEventType, this);
|
||||
|
@ -3050,6 +3053,10 @@ PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode, UINT aVir
|
|||
|
||||
event.flags |= aFlags;
|
||||
event.charCode = aCharCode;
|
||||
if (aUnshiftedCharCode || aShiftedCharCode) {
|
||||
nsAlternativeCharCode altCharCodes(aUnshiftedCharCode, aShiftedCharCode);
|
||||
event.alternativeCharCodes.AppendElement(altCharCodes);
|
||||
}
|
||||
event.keyCode = aVirtualCharCode;
|
||||
|
||||
#ifdef KE_DEBUG
|
||||
|
@ -3133,7 +3140,7 @@ BOOL nsWindow::OnKeyDown(UINT aVirtualKeyCode, UINT aScanCode, LPARAM aKeyData)
|
|||
//printf("In OnKeyDown virt: %d scan: %d\n", DOMKeyCode, aScanCode);
|
||||
#endif
|
||||
|
||||
BOOL noDefault = DispatchKeyEvent(NS_KEY_DOWN, 0, DOMKeyCode, aKeyData);
|
||||
BOOL noDefault = DispatchKeyEvent(NS_KEY_DOWN, 0, 0, 0, DOMKeyCode, aKeyData);
|
||||
|
||||
// If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
|
||||
// for almost all keys
|
||||
|
@ -3233,9 +3240,13 @@ BOOL nsWindow::OnKeyDown(UINT aVirtualKeyCode, UINT aScanCode, LPARAM aKeyData)
|
|||
if (gKbdLayout.IsDeadKey ())
|
||||
return PR_FALSE;
|
||||
|
||||
PRUint8 shiftStates [5];
|
||||
PRUint16 uniChars [5];
|
||||
PRUint8 shiftStates[5];
|
||||
PRUint16 uniChars[5];
|
||||
PRUint16 shiftedChars[5] = {0, 0, 0, 0, 0};
|
||||
PRUint16 unshiftedChars[5] = {0, 0, 0, 0, 0};
|
||||
PRUint32 numOfUniChars = 0;
|
||||
PRUint32 numOfShiftedChars = 0;
|
||||
PRUint32 numOfUnshiftedChars = 0;
|
||||
PRUint32 numOfShiftStates = 0;
|
||||
|
||||
switch (aVirtualKeyCode) {
|
||||
|
@ -3258,67 +3269,55 @@ BOOL nsWindow::OnKeyDown(UINT aVirtualKeyCode, UINT aScanCode, LPARAM aKeyData)
|
|||
numOfUniChars = 1;
|
||||
break;
|
||||
default:
|
||||
if (KeyboardLayout::IsPrintableCharKey (aVirtualKeyCode))
|
||||
numOfUniChars = numOfShiftStates = gKbdLayout.GetUniChars (uniChars, shiftStates, NS_ARRAY_LENGTH (uniChars));
|
||||
if (KeyboardLayout::IsPrintableCharKey(aVirtualKeyCode)) {
|
||||
numOfUniChars = numOfShiftStates =
|
||||
gKbdLayout.GetUniChars(uniChars, shiftStates,
|
||||
NS_ARRAY_LENGTH(uniChars));
|
||||
}
|
||||
|
||||
if (mIsControlDown ^ mIsAltDown)
|
||||
{
|
||||
// XXX
|
||||
// For both Alt+key and Ctrl+key combinations we return the latin characters A..Z and
|
||||
// numbers 0..9, ignoring the real characters returned by active keyboard layout.
|
||||
// This is required to make sure that all shortcut keys (e.g. Ctrl+c, Ctrl+1, Alt+f)
|
||||
// work the same way no matter what keyboard layout you are using.
|
||||
|
||||
if ((NS_VK_0 <= DOMKeyCode && DOMKeyCode <= NS_VK_9) ||
|
||||
(NS_VK_A <= DOMKeyCode && DOMKeyCode <= NS_VK_Z))
|
||||
{
|
||||
uniChars [0] = DOMKeyCode;
|
||||
numOfUniChars = 1;
|
||||
numOfShiftStates = 0;
|
||||
|
||||
// For letters take the Shift state into account
|
||||
if (!mIsShiftDown &&
|
||||
NS_VK_A <= DOMKeyCode && DOMKeyCode <= NS_VK_Z)
|
||||
uniChars [0] += 0x20;
|
||||
}
|
||||
else if (!anyCharMessagesRemoved && DOMKeyCode != aVirtualKeyCode) {
|
||||
switch (DOMKeyCode) {
|
||||
case NS_VK_ADD:
|
||||
uniChars [0] = '+'; numOfUniChars = 1; break;
|
||||
case NS_VK_SUBTRACT:
|
||||
uniChars [0] = '-'; numOfUniChars = 1; break;
|
||||
case NS_VK_SEMICOLON:
|
||||
// XXXmnakano I don't know whether this is correct.
|
||||
uniChars [0] = ';';
|
||||
uniChars [1] = ':';
|
||||
numOfUniChars = 2;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("implement me!");
|
||||
}
|
||||
}
|
||||
if (mIsControlDown ^ mIsAltDown) {
|
||||
numOfUnshiftedChars =
|
||||
gKbdLayout.GetUniCharsWithShiftState(aVirtualKeyCode, 0,
|
||||
unshiftedChars, NS_ARRAY_LENGTH(unshiftedChars));
|
||||
numOfShiftedChars =
|
||||
gKbdLayout.GetUniCharsWithShiftState(aVirtualKeyCode, eShift,
|
||||
shiftedChars, NS_ARRAY_LENGTH(shiftedChars));
|
||||
}
|
||||
}
|
||||
|
||||
if (numOfUniChars)
|
||||
{
|
||||
for (PRUint32 cnt = 0; cnt < numOfUniChars; cnt++)
|
||||
{
|
||||
if (cnt < numOfShiftStates)
|
||||
{
|
||||
// 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.
|
||||
mIsShiftDown = (shiftStates [cnt] & eShift) != 0;
|
||||
mIsControlDown = (shiftStates [cnt] & eCtrl) != 0;
|
||||
mIsAltDown = (shiftStates [cnt] & eAlt) != 0;
|
||||
if (numOfUniChars > 0 || numOfShiftedChars > 0 || numOfUnshiftedChars > 0) {
|
||||
PRUint32 num = PR_MAX(numOfUniChars,
|
||||
PR_MAX(numOfShiftedChars, numOfUnshiftedChars));
|
||||
PRUint32 skipUniChars = num - numOfUniChars;
|
||||
PRUint32 skipShiftedChars = num - numOfShiftedChars;
|
||||
PRUint32 skipUnshiftedChars = num - numOfUnshiftedChars;
|
||||
UINT keyCode = numOfUniChars == 0 ? DOMKeyCode : 0;
|
||||
for (PRUint32 cnt = 0; cnt < num; cnt++) {
|
||||
PRUint16 uniChar, shiftedChar, unshiftedChar;
|
||||
uniChar = shiftedChar = unshiftedChar = 0;
|
||||
if (skipUniChars <= cnt) {
|
||||
if (cnt - skipUniChars < numOfShiftStates) {
|
||||
// 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.
|
||||
mIsShiftDown = (shiftStates[cnt - skipUniChars] & eShift) != 0;
|
||||
mIsControlDown = (shiftStates[cnt - skipUniChars] & eCtrl) != 0;
|
||||
mIsAltDown = (shiftStates[cnt - skipUniChars] & eAlt) != 0;
|
||||
}
|
||||
uniChar = uniChars[cnt - skipUniChars];
|
||||
}
|
||||
|
||||
DispatchKeyEvent(NS_KEY_PRESS, uniChars [cnt], 0, aKeyData, extraFlags);
|
||||
if (skipShiftedChars <= cnt)
|
||||
shiftedChar = shiftedChars[cnt - skipShiftedChars];
|
||||
if (skipUnshiftedChars <= cnt)
|
||||
unshiftedChar = unshiftedChars[cnt - skipUnshiftedChars];
|
||||
DispatchKeyEvent(NS_KEY_PRESS, uniChar, unshiftedChar,
|
||||
shiftedChar, keyCode, aKeyData, extraFlags);
|
||||
}
|
||||
} else
|
||||
DispatchKeyEvent(NS_KEY_PRESS, 0, DOMKeyCode, aKeyData, extraFlags);
|
||||
DispatchKeyEvent(NS_KEY_PRESS, 0, 0, 0, DOMKeyCode, aKeyData, extraFlags);
|
||||
|
||||
return noDefault;
|
||||
}
|
||||
|
@ -3335,7 +3334,7 @@ BOOL nsWindow::OnKeyUp( UINT aVirtualKeyCode, UINT aScanCode, LPARAM aKeyData)
|
|||
#endif
|
||||
|
||||
aVirtualKeyCode = sIMEIsComposing ? aVirtualKeyCode : MapFromNativeToDOM(aVirtualKeyCode);
|
||||
BOOL result = DispatchKeyEvent(NS_KEY_UP, 0, aVirtualKeyCode, aKeyData);
|
||||
BOOL result = DispatchKeyEvent(NS_KEY_UP, 0, 0, 0, aVirtualKeyCode, aKeyData);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3412,7 +3411,8 @@ BOOL nsWindow::OnChar(UINT charCode, LPARAM keyData, PRUint32 aFlags)
|
|||
uniChar = towlower(uniChar);
|
||||
}
|
||||
|
||||
PRBool result = DispatchKeyEvent(NS_KEY_PRESS, uniChar, charCode, 0, aFlags);
|
||||
PRBool result = DispatchKeyEvent(NS_KEY_PRESS, uniChar, 0, 0,
|
||||
charCode, 0, aFlags);
|
||||
mIsAltDown = saveIsAltDown;
|
||||
mIsControlDown = saveIsControlDown;
|
||||
return result;
|
||||
|
@ -6535,7 +6535,7 @@ BOOL nsWindow::OnIMEChar(BYTE aByte1, BYTE aByte2, LPARAM aKeyState)
|
|||
|
||||
// We need to return TRUE here so that Windows doesn't
|
||||
// send two WM_CHAR msgs
|
||||
DispatchKeyEvent(NS_KEY_PRESS, uniChar, 0, 0);
|
||||
DispatchKeyEvent(NS_KEY_PRESS, uniChar, 0, 0, 0, 0);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -6815,7 +6815,7 @@ BOOL nsWindow::OnIMENotify(WPARAM aIMN, LPARAM aData, LRESULT *oResult)
|
|||
mIsControlDown = PR_FALSE;
|
||||
mIsAltDown = PR_TRUE;
|
||||
|
||||
DispatchKeyEvent(NS_KEY_PRESS, 0, 192, 0); // XXX hack hack hack
|
||||
DispatchKeyEvent(NS_KEY_PRESS, 0, 0, 0, 192, 0); // XXX hack hack hack
|
||||
if (aIMN == IMN_SETOPENSTATUS)
|
||||
sIMEIsStatusChanged = PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -331,8 +331,12 @@ protected:
|
|||
nsRect& aEventResult,
|
||||
nsRect& aResult);
|
||||
|
||||
virtual PRBool DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode, UINT aVirtualCharCode,
|
||||
LPARAM aKeyCode, PRUint32 aFlags = 0);
|
||||
virtual PRBool DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode,
|
||||
PRUint32 aUnshiftedCharCode,
|
||||
PRUint32 aShiftedCharCodes,
|
||||
UINT aVirtualCharCode,
|
||||
LPARAM aKeyCode,
|
||||
PRUint32 aFlags = 0);
|
||||
|
||||
virtual PRBool DispatchFocus(PRUint32 aEventType, PRBool isMozWindowTakingFocus);
|
||||
virtual PRBool OnScroll(UINT scrollCode, int cPos);
|
||||
|
|
Загрузка…
Ссылка в новой задаче