зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1101975, handle access keys in content process before menus, r=masayuki
This commit is contained in:
Родитель
33054a51f2
Коммит
405358d4b3
|
@ -7134,7 +7134,7 @@ nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsContentUtils::CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
|
||||
CallOnRemoteChildFunction aCallback,
|
||||
void* aArg)
|
||||
|
@ -7150,7 +7150,9 @@ nsContentUtils::CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
|
|||
|
||||
nsCOMPtr<nsIMessageBroadcaster> nonLeafMM = do_QueryInterface(childMM);
|
||||
if (nonLeafMM) {
|
||||
CallOnAllRemoteChildren(nonLeafMM, aCallback, aArg);
|
||||
if (CallOnAllRemoteChildren(nonLeafMM, aCallback, aArg)) {
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -7162,10 +7164,14 @@ nsContentUtils::CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
|
|||
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
|
||||
TabParent* remote = TabParent::GetFrom(fl);
|
||||
if (remote && aCallback) {
|
||||
aCallback(remote, aArg);
|
||||
if (aCallback(remote, aArg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -171,7 +171,7 @@ struct EventNameMapping
|
|||
mozilla::EventClassID mEventClassID;
|
||||
};
|
||||
|
||||
typedef void (*CallOnRemoteChildFunction) (mozilla::dom::TabParent* aTabParent,
|
||||
typedef bool (*CallOnRemoteChildFunction) (mozilla::dom::TabParent* aTabParent,
|
||||
void* aArg);
|
||||
|
||||
class nsContentUtils
|
||||
|
@ -2379,7 +2379,7 @@ public:
|
|||
|
||||
/*
|
||||
* Call the given callback on all remote children of the given top-level
|
||||
* window.
|
||||
* window. Return true from the callback to stop calling further children.
|
||||
*/
|
||||
static void CallOnAllRemoteChildren(nsPIDOMWindowOuter* aWindow,
|
||||
CallOnRemoteChildFunction aCallback,
|
||||
|
@ -2598,7 +2598,7 @@ private:
|
|||
static AutocompleteAttrState InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal,
|
||||
mozilla::dom::AutocompleteInfo& aInfo);
|
||||
|
||||
static void CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
|
||||
static bool CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
|
||||
CallOnRemoteChildFunction aCallback,
|
||||
void* aArg);
|
||||
|
||||
|
|
|
@ -1110,11 +1110,12 @@ nsFocusManager::EnsureCurrentWidgetFocused()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ActivateOrDeactivateChild(TabParent* aParent, void* aArg)
|
||||
{
|
||||
bool active = static_cast<bool>(aArg);
|
||||
Unused << aParent->SendParentActivated(active);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -682,6 +682,7 @@ GK_ATOM(ol, "ol")
|
|||
GK_ATOM(omitXmlDeclaration, "omit-xml-declaration")
|
||||
GK_ATOM(ona2dpstatuschanged, "ona2dpstatuschanged")
|
||||
GK_ATOM(onabort, "onabort")
|
||||
GK_ATOM(onmozaccesskeynotfound, "onmozaccesskeynotfound")
|
||||
GK_ATOM(onactivate, "onactivate")
|
||||
GK_ATOM(onadapteradded, "onadapteradded")
|
||||
GK_ATOM(onadapterremoved, "onadapterremoved")
|
||||
|
|
|
@ -270,6 +270,10 @@ NON_IDL_EVENT(mozbrowserafterkeyup,
|
|||
eAfterKeyUp,
|
||||
EventNameType_None,
|
||||
eBeforeAfterKeyboardEventClass)
|
||||
NON_IDL_EVENT(mozaccesskeynotfound,
|
||||
eAccessKeyNotFound,
|
||||
EventNameType_None,
|
||||
eKeyboardEventClass)
|
||||
EVENT(loadeddata,
|
||||
eLoadedData,
|
||||
EventNameType_HTML,
|
||||
|
|
|
@ -732,15 +732,18 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
modifierMask |= NS_MODIFIER_OS;
|
||||
|
||||
// Prevent keyboard scrolling while an accesskey modifier is in use.
|
||||
if (modifierMask &&
|
||||
(modifierMask == Prefs::ChromeAccessModifierMask() ||
|
||||
modifierMask == Prefs::ContentAccessModifierMask())) {
|
||||
AutoTArray<uint32_t, 10> accessCharCodes;
|
||||
keyEvent->GetAccessKeyCandidates(accessCharCodes);
|
||||
if (modifierMask) {
|
||||
bool matchesContentAccessKey = (modifierMask == Prefs::ContentAccessModifierMask());
|
||||
|
||||
if (modifierMask == Prefs::ChromeAccessModifierMask() ||
|
||||
matchesContentAccessKey) {
|
||||
AutoTArray<uint32_t, 10> accessCharCodes;
|
||||
keyEvent->GetAccessKeyCandidates(accessCharCodes);
|
||||
|
||||
if (HandleAccessKey(aPresContext, accessCharCodes,
|
||||
keyEvent->IsTrusted(), modifierMask)) {
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
if (HandleAccessKey(keyEvent, aPresContext, accessCharCodes,
|
||||
modifierMask, matchesContentAccessKey)) {
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1036,21 +1039,21 @@ EventStateManager::GetAccessKeyLabelPrefix(Element* aElement, nsAString& aPrefix
|
|||
}
|
||||
}
|
||||
|
||||
struct AccessKeyInfo
|
||||
struct MOZ_STACK_CLASS AccessKeyInfo
|
||||
{
|
||||
WidgetKeyboardEvent* event;
|
||||
nsTArray<uint32_t>& charCodes;
|
||||
bool isTrusted;
|
||||
int32_t modifierMask;
|
||||
|
||||
AccessKeyInfo(nsTArray<uint32_t>& aCharCodes, bool aIsTrusted, int32_t aModifierMask)
|
||||
: charCodes(aCharCodes)
|
||||
, isTrusted(aIsTrusted)
|
||||
AccessKeyInfo(WidgetKeyboardEvent* aEvent, nsTArray<uint32_t>& aCharCodes, int32_t aModifierMask)
|
||||
: event(aEvent)
|
||||
, charCodes(aCharCodes)
|
||||
, modifierMask(aModifierMask)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
static bool
|
||||
HandleAccessKeyInRemoteChild(TabParent* aTabParent, void* aArg)
|
||||
{
|
||||
AccessKeyInfo* accessKeyInfo = static_cast<AccessKeyInfo*>(aArg);
|
||||
|
@ -1059,15 +1062,21 @@ HandleAccessKeyInRemoteChild(TabParent* aTabParent, void* aArg)
|
|||
bool active;
|
||||
aTabParent->GetDocShellIsActive(&active);
|
||||
if (active) {
|
||||
aTabParent->HandleAccessKey(accessKeyInfo->charCodes, accessKeyInfo->isTrusted,
|
||||
accessKeyInfo->event->mAccessKeyForwardedToChild = true;
|
||||
aTabParent->HandleAccessKey(*accessKeyInfo->event,
|
||||
accessKeyInfo->charCodes,
|
||||
accessKeyInfo->modifierMask);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EventStateManager::HandleAccessKey(nsPresContext* aPresContext,
|
||||
EventStateManager::HandleAccessKey(WidgetKeyboardEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsTArray<uint32_t>& aAccessCharCodes,
|
||||
bool aIsTrusted,
|
||||
bool aMatchesContentAccessKey,
|
||||
nsIDocShellTreeItem* aBubbledFrom,
|
||||
ProcessingAccessKeyState aAccessKeyState,
|
||||
int32_t aModifierMask)
|
||||
|
@ -1082,7 +1091,7 @@ EventStateManager::HandleAccessKey(nsPresContext* aPresContext,
|
|||
if (mAccessKeys.Count() > 0 &&
|
||||
aModifierMask == GetAccessModifierMaskFor(docShell)) {
|
||||
// Someone registered an accesskey. Find and activate it.
|
||||
if (ExecuteAccessKey(aAccessCharCodes, aIsTrusted)) {
|
||||
if (ExecuteAccessKey(aAccessCharCodes, aEvent->IsTrusted())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1115,7 +1124,8 @@ EventStateManager::HandleAccessKey(nsPresContext* aPresContext,
|
|||
static_cast<EventStateManager*>(subPC->EventStateManager());
|
||||
|
||||
if (esm &&
|
||||
esm->HandleAccessKey(subPC, aAccessCharCodes, aIsTrusted, nullptr,
|
||||
esm->HandleAccessKey(aEvent, subPC, aAccessCharCodes,
|
||||
aMatchesContentAccessKey, nullptr,
|
||||
eAccessKeyProcessingDown, aModifierMask)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1137,22 +1147,27 @@ EventStateManager::HandleAccessKey(nsPresContext* aPresContext,
|
|||
EventStateManager* esm =
|
||||
static_cast<EventStateManager*>(parentPC->EventStateManager());
|
||||
if (esm &&
|
||||
esm->HandleAccessKey(parentPC, aAccessCharCodes, aIsTrusted, docShell,
|
||||
eAccessKeyProcessingUp, aModifierMask)) {
|
||||
esm->HandleAccessKey(aEvent, parentPC, aAccessCharCodes,
|
||||
aMatchesContentAccessKey, docShell,
|
||||
eAccessKeyProcessingDown, aModifierMask)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}// if end. bubble up process
|
||||
|
||||
// Now try remote children
|
||||
if (mDocument && mDocument->GetWindow()) {
|
||||
// If the content access key modifier is pressed, try remote children
|
||||
if (aMatchesContentAccessKey && mDocument && mDocument->GetWindow()) {
|
||||
// If the focus is currently on a node with a TabParent, the key event will
|
||||
// get forwarded to the child process and HandleAccessKey called from there.
|
||||
// If focus is somewhere else, then we need to check the remote children.
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
nsIContent* focusedContent = fm ? fm->GetFocusedContent() : nullptr;
|
||||
if (!TabParent::GetFrom(focusedContent)) {
|
||||
AccessKeyInfo accessKeyInfo(aAccessCharCodes, aIsTrusted, aModifierMask);
|
||||
if (TabParent::GetFrom(focusedContent)) {
|
||||
// A remote child process is focused. The key event should get sent to
|
||||
// the child process.
|
||||
aEvent->mAccessKeyForwardedToChild = true;
|
||||
} else {
|
||||
AccessKeyInfo accessKeyInfo(aEvent, aAccessCharCodes, aModifierMask);
|
||||
nsContentUtils::CallOnAllRemoteChildren(mDocument->GetWindow(),
|
||||
HandleAccessKeyInRemoteChild, &accessKeyInfo);
|
||||
}
|
||||
|
|
|
@ -183,13 +183,15 @@ public:
|
|||
|
||||
static void GetAccessKeyLabelPrefix(dom::Element* aElement, nsAString& aPrefix);
|
||||
|
||||
bool HandleAccessKey(nsPresContext* aPresContext,
|
||||
bool HandleAccessKey(WidgetKeyboardEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsTArray<uint32_t>& aAccessCharCodes,
|
||||
bool aIsTrusted,
|
||||
int32_t aModifierMask)
|
||||
int32_t aModifierMask,
|
||||
bool aMatchesContentAccessKey)
|
||||
{
|
||||
return HandleAccessKey(aPresContext, aAccessCharCodes, aIsTrusted,
|
||||
nullptr, eAccessKeyProcessingNormal, aModifierMask);
|
||||
return HandleAccessKey(aEvent, aPresContext, aAccessCharCodes,
|
||||
aMatchesContentAccessKey, nullptr,
|
||||
eAccessKeyProcessingNormal, aModifierMask);
|
||||
}
|
||||
|
||||
nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer,
|
||||
|
@ -435,9 +437,10 @@ protected:
|
|||
* on descendant docshells first, then on the ancestor (with |aBubbledFrom|
|
||||
* set to the docshell associated with |this|), until something matches.
|
||||
*
|
||||
* @param aEvent the keyboard event triggering the acccess key
|
||||
* @param aPresContext the presentation context
|
||||
* @param aAccessCharCodes list of charcode candidates
|
||||
* @param aIsTrusted true if triggered by a trusted key event
|
||||
* @param aMatchesContentAccessKey true if the content accesskey modifier is pressed
|
||||
* @param aBubbledFrom is used by an ancestor to avoid calling HandleAccessKey()
|
||||
* on the child the call originally came from, i.e. this is the child
|
||||
* that recursively called us in its Up phase. The initial caller
|
||||
|
@ -447,15 +450,16 @@ protected:
|
|||
* processing children and Up when recursively calling its ancestor.
|
||||
* @param aModifierMask modifier mask for the key event
|
||||
*/
|
||||
bool HandleAccessKey(nsPresContext* aPresContext,
|
||||
nsTArray<uint32_t>& aAccessCharCodes,
|
||||
bool aIsTrusted,
|
||||
nsIDocShellTreeItem* aBubbledFrom,
|
||||
ProcessingAccessKeyState aAccessKeyState,
|
||||
int32_t aModifierMask);
|
||||
bool HandleAccessKey(WidgetKeyboardEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsTArray<uint32_t>& aAccessCharCodes,
|
||||
bool aMatchesContentAccessKey,
|
||||
nsIDocShellTreeItem* aBubbledFrom,
|
||||
ProcessingAccessKeyState aAccessKeyState,
|
||||
int32_t aModifierMask);
|
||||
|
||||
bool ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
|
||||
bool aIsTrustedEvent);
|
||||
bool aIsTrustedEvent);
|
||||
|
||||
//---------------------------------------------
|
||||
// DocShell Focus Traversal Methods
|
||||
|
|
|
@ -198,6 +198,7 @@ KeyboardEvent::CharCode()
|
|||
case eAfterKeyUp:
|
||||
return 0;
|
||||
case eKeyPress:
|
||||
case eAccessKeyNotFound:
|
||||
return mEvent->AsKeyboardEvent()->charCode;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -506,6 +506,8 @@ parent:
|
|||
*/
|
||||
sync GetTabCount() returns (uint32_t value);
|
||||
|
||||
async AccessKeyNotHandled(WidgetKeyboardEvent event);
|
||||
|
||||
child:
|
||||
async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
|
||||
|
||||
|
@ -746,11 +748,12 @@ child:
|
|||
* A potential accesskey was just pressed. Look for accesskey targets
|
||||
* using the list of provided charCodes.
|
||||
*
|
||||
* @param charCode array of potential character codes
|
||||
* @param event keyboard event
|
||||
* @param isTrusted true if triggered by a trusted key event
|
||||
* @param modifierMask indicates which accesskey modifiers are pressed
|
||||
*/
|
||||
async HandleAccessKey(uint32_t[] charCodes, bool isTrusted, int32_t modifierMask);
|
||||
async HandleAccessKey(WidgetKeyboardEvent event,
|
||||
uint32_t[] charCodes, int32_t modifierMask);
|
||||
|
||||
/**
|
||||
* Propagate a refresh to the child process
|
||||
|
|
|
@ -2124,10 +2124,17 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
|
|||
mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
// If a response is desired from the content process, resend the key event.
|
||||
// If mAccessKeyForwardedToChild is set, then don't resend the key event yet
|
||||
// as RecvHandleAccessKey will do this.
|
||||
if (localEvent.mFlags.mWantReplyFromContentProcess) {
|
||||
SendReplyKeyEvent(localEvent);
|
||||
}
|
||||
|
||||
if (localEvent.mAccessKeyForwardedToChild) {
|
||||
SendAccessKeyNotHandled(localEvent);
|
||||
}
|
||||
|
||||
if (PresShell::BeforeAfterKeyboardEventEnabled()) {
|
||||
SendDispatchAfterKeyboardEvent(localEvent);
|
||||
}
|
||||
|
@ -2390,8 +2397,8 @@ TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
|
|||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvHandleAccessKey(nsTArray<uint32_t>&& aCharCodes,
|
||||
const bool& aIsTrusted,
|
||||
TabChild::RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
|
||||
nsTArray<uint32_t>&& aCharCodes,
|
||||
const int32_t& aModifierMask)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> document(GetDocument());
|
||||
|
@ -2399,7 +2406,16 @@ TabChild::RecvHandleAccessKey(nsTArray<uint32_t>&& aCharCodes,
|
|||
if (presShell) {
|
||||
nsPresContext* pc = presShell->GetPresContext();
|
||||
if (pc) {
|
||||
pc->EventStateManager()->HandleAccessKey(pc, aCharCodes, aIsTrusted, aModifierMask);
|
||||
if (!pc->EventStateManager()->
|
||||
HandleAccessKey(&(const_cast<WidgetKeyboardEvent&>(aEvent)),
|
||||
pc, aCharCodes,
|
||||
aModifierMask, true)) {
|
||||
// If no accesskey was found, inform the parent so that accesskeys on
|
||||
// menus can be handled.
|
||||
WidgetKeyboardEvent localEvent(aEvent);
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
SendAccessKeyNotHandled(localEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -566,8 +566,8 @@ public:
|
|||
virtual bool
|
||||
RecvThemeChanged(nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache) override;
|
||||
|
||||
virtual bool RecvHandleAccessKey(nsTArray<uint32_t>&& aCharCodes,
|
||||
const bool& aIsTrusted,
|
||||
virtual bool RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
|
||||
nsTArray<uint32_t>&& aCharCodes,
|
||||
const int32_t& aModifierMask) override;
|
||||
|
||||
virtual bool RecvAudioChannelChangeNotification(const uint32_t& aAudioChannel,
|
||||
|
|
|
@ -988,12 +988,12 @@ TabParent::ThemeChanged()
|
|||
}
|
||||
|
||||
void
|
||||
TabParent::HandleAccessKey(nsTArray<uint32_t>& aCharCodes,
|
||||
const bool& aIsTrusted,
|
||||
TabParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent,
|
||||
nsTArray<uint32_t>& aCharCodes,
|
||||
const int32_t& aModifierMask)
|
||||
{
|
||||
if (!mIsDestroyed) {
|
||||
Unused << SendHandleAccessKey(aCharCodes, aIsTrusted, aModifierMask);
|
||||
Unused << SendHandleAccessKey(aEvent, aCharCodes, aModifierMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2130,6 +2130,31 @@ TabParent::RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvAccessKeyNotHandled(const WidgetKeyboardEvent& aEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mFrameElement, true);
|
||||
|
||||
WidgetKeyboardEvent localEvent(aEvent);
|
||||
localEvent.mMessage = eAccessKeyNotFound;
|
||||
localEvent.mAccessKeyForwardedToChild = false;
|
||||
|
||||
// Here we convert the WidgetEvent that we received to an nsIDOMEvent
|
||||
// to be able to dispatch it to the <browser> element as the target element.
|
||||
nsIDocument* doc = mFrameElement->OwnerDoc();
|
||||
nsIPresShell* presShell = doc->GetShell();
|
||||
NS_ENSURE_TRUE(presShell, true);
|
||||
|
||||
if (presShell->CanDispatchEvent()) {
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
NS_ENSURE_TRUE(presContext, true);
|
||||
|
||||
EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
|
||||
{
|
||||
|
|
|
@ -174,6 +174,9 @@ public:
|
|||
virtual bool
|
||||
RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent) override;
|
||||
|
||||
virtual bool
|
||||
RecvAccessKeyNotHandled(const WidgetKeyboardEvent& aEvent) override;
|
||||
|
||||
virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
|
||||
PRenderFrameParent* aRenderFrame,
|
||||
const nsString& aURL,
|
||||
|
@ -364,8 +367,8 @@ public:
|
|||
|
||||
void ThemeChanged();
|
||||
|
||||
void HandleAccessKey(nsTArray<uint32_t>& aCharCodes,
|
||||
const bool& aIsTrusted,
|
||||
void HandleAccessKey(const WidgetKeyboardEvent& aEvent,
|
||||
nsTArray<uint32_t>& aCharCodes,
|
||||
const int32_t& aModifierMask);
|
||||
|
||||
void Activate();
|
||||
|
|
|
@ -1596,10 +1596,11 @@ nsPresContext::ThemeChanged()
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static bool
|
||||
NotifyThemeChanged(TabParent* aTabParent, void* aArg)
|
||||
{
|
||||
aTabParent->ThemeChanged();
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1948,11 +1949,12 @@ nsPresContext::HandleMediaFeatureValuesChangedEvent()
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static bool
|
||||
NotifyTabSizeModeChanged(TabParent* aTab, void* aArg)
|
||||
{
|
||||
nsSizeMode* sizeMode = static_cast<nsSizeMode*>(aArg);
|
||||
aTab->SizeModeChanged(*sizeMode);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -79,6 +79,7 @@ nsMenuBarFrame::Init(nsIContent* aContent,
|
|||
mTarget->AddSystemEventListener(NS_LITERAL_STRING("keypress"), mMenuBarListener, false);
|
||||
mTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"), mMenuBarListener, false);
|
||||
mTarget->AddSystemEventListener(NS_LITERAL_STRING("keyup"), mMenuBarListener, false);
|
||||
mTarget->AddSystemEventListener(NS_LITERAL_STRING("mozaccesskeynotfound"), mMenuBarListener, false);
|
||||
|
||||
// mousedown event should be handled in all phase
|
||||
mTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mMenuBarListener, true);
|
||||
|
@ -416,6 +417,7 @@ nsMenuBarFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keypress"), mMenuBarListener, false);
|
||||
mTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), mMenuBarListener, false);
|
||||
mTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keyup"), mMenuBarListener, false);
|
||||
mTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mozaccesskeynotfound"), mMenuBarListener, false);
|
||||
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), mMenuBarListener, true);
|
||||
mTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), mMenuBarListener, false);
|
||||
|
|
|
@ -199,83 +199,82 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
aKeyEvent->GetIsTrusted(&trustedEvent);
|
||||
}
|
||||
|
||||
if (!trustedEvent)
|
||||
if (!trustedEvent) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult retVal = NS_OK; // default is to not consume event
|
||||
|
||||
InitAccessKey();
|
||||
|
||||
if (mAccessKey)
|
||||
{
|
||||
bool preventDefault;
|
||||
aKeyEvent->GetDefaultPrevented(&preventDefault);
|
||||
if (!preventDefault) {
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
|
||||
uint32_t keyCode, charCode;
|
||||
keyEvent->GetKeyCode(&keyCode);
|
||||
keyEvent->GetCharCode(&charCode);
|
||||
// If accesskey handling was forwarded to a child process, wait for
|
||||
// the mozaccesskeynotfound event before handling accesskeys.
|
||||
WidgetKeyboardEvent* nativeKeyEvent =
|
||||
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
|
||||
if (nativeKeyEvent->mAccessKeyForwardedToChild) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool hasAccessKeyCandidates = charCode != 0;
|
||||
if (!hasAccessKeyCandidates) {
|
||||
WidgetKeyboardEvent* nativeKeyEvent =
|
||||
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
|
||||
if (nativeKeyEvent) {
|
||||
AutoTArray<uint32_t, 10> keys;
|
||||
nativeKeyEvent->GetAccessKeyCandidates(keys);
|
||||
hasAccessKeyCandidates = !keys.IsEmpty();
|
||||
}
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
|
||||
uint32_t keyCode, charCode;
|
||||
keyEvent->GetKeyCode(&keyCode);
|
||||
keyEvent->GetCharCode(&charCode);
|
||||
|
||||
bool hasAccessKeyCandidates = charCode != 0;
|
||||
if (!hasAccessKeyCandidates) {
|
||||
if (nativeKeyEvent) {
|
||||
AutoTArray<uint32_t, 10> keys;
|
||||
nativeKeyEvent->GetAccessKeyCandidates(keys);
|
||||
hasAccessKeyCandidates = !keys.IsEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the access key flag unless we are pressing the access key.
|
||||
if (keyCode != (uint32_t)mAccessKey) {
|
||||
mAccessKeyDownCanceled = true;
|
||||
// Cancel the access key flag unless we are pressing the access key.
|
||||
if (keyCode != (uint32_t)mAccessKey) {
|
||||
mAccessKeyDownCanceled = true;
|
||||
}
|
||||
|
||||
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.
|
||||
nsMenuFrame* result = mMenuBarFrame->FindMenuWithShortcut(keyEvent);
|
||||
if (result) {
|
||||
mMenuBarFrame->SetActiveByKeyboard();
|
||||
mMenuBarFrame->SetActive(true);
|
||||
result->OpenMenu(true);
|
||||
|
||||
// The opened menu will listen next keyup event.
|
||||
// Therefore, we should clear the keydown flags here.
|
||||
mAccessKeyDown = mAccessKeyDownCanceled = false;
|
||||
|
||||
aKeyEvent->StopPropagation();
|
||||
aKeyEvent->PreventDefault();
|
||||
}
|
||||
}
|
||||
#ifndef XP_MACOSX
|
||||
// Also need to handle F10 specially on Non-Mac platform.
|
||||
else if (nativeKeyEvent->mMessage == eKeyPress && keyCode == NS_VK_F10) {
|
||||
if ((GetModifiersForAccessKey(keyEvent) & ~MODIFIER_CONTROL) == 0) {
|
||||
// The F10 key just went down by itself or with ctrl pressed.
|
||||
// In Windows, both of these activate the menu bar.
|
||||
mMenuBarFrame->SetActiveByKeyboard();
|
||||
ToggleMenuActiveState();
|
||||
|
||||
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.
|
||||
nsMenuFrame* result = mMenuBarFrame->FindMenuWithShortcut(keyEvent);
|
||||
if (result) {
|
||||
mMenuBarFrame->SetActiveByKeyboard();
|
||||
mMenuBarFrame->SetActive(true);
|
||||
result->OpenMenu(true);
|
||||
|
||||
// The opened menu will listen next keyup event.
|
||||
// Therefore, we should clear the keydown flags here.
|
||||
mAccessKeyDown = mAccessKeyDownCanceled = false;
|
||||
|
||||
if (mMenuBarFrame->IsActive()) {
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
// In GTK, this also opens the first menu.
|
||||
mMenuBarFrame->GetCurrentMenuItem()->OpenMenu(true);
|
||||
#endif
|
||||
aKeyEvent->StopPropagation();
|
||||
aKeyEvent->PreventDefault();
|
||||
retVal = NS_OK; // I am consuming event
|
||||
}
|
||||
}
|
||||
#ifndef XP_MACOSX
|
||||
// Also need to handle F10 specially on Non-Mac platform.
|
||||
else if (keyCode == NS_VK_F10) {
|
||||
if ((GetModifiersForAccessKey(keyEvent) & ~MODIFIER_CONTROL) == 0) {
|
||||
// The F10 key just went down by itself or with ctrl pressed.
|
||||
// In Windows, both of these activate the menu bar.
|
||||
mMenuBarFrame->SetActiveByKeyboard();
|
||||
ToggleMenuActiveState();
|
||||
|
||||
if (mMenuBarFrame->IsActive()) {
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
// In GTK, this also opens the first menu.
|
||||
mMenuBarFrame->GetCurrentMenuItem()->OpenMenu(true);
|
||||
#endif
|
||||
aKeyEvent->StopPropagation();
|
||||
aKeyEvent->PreventDefault();
|
||||
return NS_OK; // consume the event
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !XP_MACOSX
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -425,6 +424,9 @@ nsMenuBarListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
if (eventType.EqualsLiteral("keypress")) {
|
||||
return KeyPress(aEvent);
|
||||
}
|
||||
if (eventType.EqualsLiteral("mozaccesskeynotfound")) {
|
||||
return KeyPress(aEvent);
|
||||
}
|
||||
if (eventType.EqualsLiteral("blur")) {
|
||||
return Blur(aEvent);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,12 @@ NS_EVENT_MESSAGE(eAfterKeyDown)
|
|||
NS_EVENT_MESSAGE(eBeforeKeyUp)
|
||||
NS_EVENT_MESSAGE(eAfterKeyUp)
|
||||
|
||||
// This message is sent after a content process handles a key event or accesskey
|
||||
// to indicate that an potential accesskey was not found. The parent process may
|
||||
// then respond by, for example, opening menus and processing other shortcuts.
|
||||
// It inherits its properties from a keypress event.
|
||||
NS_EVENT_MESSAGE(eAccessKeyNotFound)
|
||||
|
||||
NS_EVENT_MESSAGE(eResize)
|
||||
NS_EVENT_MESSAGE(eScroll)
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ protected:
|
|||
, mIsRepeat(false)
|
||||
, mIsComposing(false)
|
||||
, mIsReserved(false)
|
||||
, mAccessKeyForwardedToChild(false)
|
||||
, mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
|
||||
, mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
|
||||
, mNativeKeyEvent(nullptr)
|
||||
|
@ -138,6 +139,7 @@ public:
|
|||
, mIsRepeat(false)
|
||||
, mIsComposing(false)
|
||||
, mIsReserved(false)
|
||||
, mAccessKeyForwardedToChild(false)
|
||||
, mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
|
||||
, mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
|
||||
, mNativeKeyEvent(nullptr)
|
||||
|
@ -220,6 +222,11 @@ public:
|
|||
// Indicates if the key combination is reserved by chrome. This is set by
|
||||
// nsXBLWindowKeyHandler at capturing phase of the default event group.
|
||||
bool mIsReserved;
|
||||
// True if accesskey handling was forwarded to the child via
|
||||
// TabParent::HandleAccessKey. In this case, parent process menu access key
|
||||
// handling should be delayed until it is determined that there exists no
|
||||
// overriding access key in the content process.
|
||||
bool mAccessKeyForwardedToChild;
|
||||
// DOM KeyboardEvent.key
|
||||
KeyNameIndex mKeyNameIndex;
|
||||
// DOM KeyboardEvent.code
|
||||
|
@ -374,6 +381,7 @@ public:
|
|||
mIsRepeat = aEvent.mIsRepeat;
|
||||
mIsComposing = aEvent.mIsComposing;
|
||||
mIsReserved = aEvent.mIsReserved;
|
||||
mAccessKeyForwardedToChild = aEvent.mAccessKeyForwardedToChild;
|
||||
mKeyNameIndex = aEvent.mKeyNameIndex;
|
||||
mCodeNameIndex = aEvent.mCodeNameIndex;
|
||||
mKeyValue = aEvent.mKeyValue;
|
||||
|
|
|
@ -171,6 +171,7 @@ WidgetEvent::HasKeyEventMessage() const
|
|||
case eBeforeKeyUp:
|
||||
case eAfterKeyDown:
|
||||
case eAfterKeyUp:
|
||||
case eAccessKeyNotFound:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -399,6 +399,7 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
|
|||
WriteParam(aMsg, aParam.isChar);
|
||||
WriteParam(aMsg, aParam.mIsRepeat);
|
||||
WriteParam(aMsg, aParam.mIsReserved);
|
||||
WriteParam(aMsg, aParam.mAccessKeyForwardedToChild);
|
||||
WriteParam(aMsg, aParam.location);
|
||||
WriteParam(aMsg, aParam.mUniqueId);
|
||||
WriteParam(aMsg, aParam.mIsSynthesizedByTIP);
|
||||
|
@ -434,6 +435,7 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
|
|||
ReadParam(aMsg, aIter, &aResult->isChar) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRepeat) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsReserved) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mAccessKeyForwardedToChild) &&
|
||||
ReadParam(aMsg, aIter, &aResult->location) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mUniqueId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsSynthesizedByTIP) &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче