зеркало из https://github.com/mozilla/gecko-dev.git
Bug 989198, Patch 3: Dispatch BeforeAfterKeyboardEvent on b2g, r=smaug
--- b2g/app/b2g.js | 3 + content/base/src/nsGkAtomList.h | 4 + dom/events/EventNameList.h | 16 +++ dom/events/EventStateManager.cpp | 6 + dom/ipc/PBrowser.ipdl | 2 + dom/ipc/TabChild.cpp | 6 +- dom/ipc/TabParent.cpp | 24 ++++ dom/ipc/TabParent.h | 1 + layout/base/nsIPresShell.h | 12 +- layout/base/nsPresShell.cpp | 250 ++++++++++++++++++++++++++++++++++++++ layout/base/nsPresShell.h | 26 ++++ modules/libpref/init/all.js | 3 + 12 files changed, 350 insertions(+), 3 deletions(-)
This commit is contained in:
Родитель
303bfb5736
Коммит
bd5a3188f8
|
@ -788,6 +788,9 @@ pref("dom.ipc.systemMessageCPULockTimeoutSec", 30);
|
||||||
// Ignore the "dialog=1" feature in window.open.
|
// Ignore the "dialog=1" feature in window.open.
|
||||||
pref("dom.disable_window_open_dialog_feature", true);
|
pref("dom.disable_window_open_dialog_feature", true);
|
||||||
|
|
||||||
|
// Enable before keyboard events and after keyboard events.
|
||||||
|
pref("dom.beforeAfterKeyboardEvent.enabled", true);
|
||||||
|
|
||||||
// Screen reader support
|
// Screen reader support
|
||||||
pref("accessibility.accessfu.activate", 2);
|
pref("accessibility.accessfu.activate", 2);
|
||||||
pref("accessibility.accessfu.quicknav_modes", "Link,Heading,FormElement,Landmark,ListItem");
|
pref("accessibility.accessfu.quicknav_modes", "Link,Heading,FormElement,Landmark,ListItem");
|
||||||
|
|
|
@ -793,6 +793,10 @@ GK_ATOM(onmouseover, "onmouseover")
|
||||||
GK_ATOM(onMozMouseHittest, "onMozMouseHittest")
|
GK_ATOM(onMozMouseHittest, "onMozMouseHittest")
|
||||||
GK_ATOM(onmouseup, "onmouseup")
|
GK_ATOM(onmouseup, "onmouseup")
|
||||||
GK_ATOM(onMozAfterPaint, "onMozAfterPaint")
|
GK_ATOM(onMozAfterPaint, "onMozAfterPaint")
|
||||||
|
GK_ATOM(onmozbrowserafterkeydown, "onmozbrowserafterkeydown")
|
||||||
|
GK_ATOM(onmozbrowserafterkeyup, "onmozbrowserafterkeyup")
|
||||||
|
GK_ATOM(onmozbrowserbeforekeydown, "onmozbrowserbeforekeydown")
|
||||||
|
GK_ATOM(onmozbrowserbeforekeyup, "onmozbrowserbeforekeyup")
|
||||||
GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
|
GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
|
||||||
GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror")
|
GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror")
|
||||||
GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange")
|
GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange")
|
||||||
|
|
|
@ -237,6 +237,22 @@ EVENT(keyup,
|
||||||
NS_KEY_UP,
|
NS_KEY_UP,
|
||||||
EventNameType_HTMLXUL,
|
EventNameType_HTMLXUL,
|
||||||
eKeyboardEventClass)
|
eKeyboardEventClass)
|
||||||
|
NON_IDL_EVENT(mozbrowserbeforekeydown,
|
||||||
|
NS_KEY_BEFORE_DOWN,
|
||||||
|
EventNameType_None,
|
||||||
|
eBeforeAfterKeyboardEventClass)
|
||||||
|
NON_IDL_EVENT(mozbrowserafterkeydown,
|
||||||
|
NS_KEY_AFTER_DOWN,
|
||||||
|
EventNameType_None,
|
||||||
|
eBeforeAfterKeyboardEventClass)
|
||||||
|
NON_IDL_EVENT(mozbrowserbeforekeyup,
|
||||||
|
NS_KEY_BEFORE_UP,
|
||||||
|
EventNameType_None,
|
||||||
|
eBeforeAfterKeyboardEventClass)
|
||||||
|
NON_IDL_EVENT(mozbrowserafterkeyup,
|
||||||
|
NS_KEY_AFTER_UP,
|
||||||
|
EventNameType_None,
|
||||||
|
eBeforeAfterKeyboardEventClass)
|
||||||
EVENT(loadeddata,
|
EVENT(loadeddata,
|
||||||
NS_LOADEDDATA,
|
NS_LOADEDDATA,
|
||||||
EventNameType_HTML,
|
EventNameType_HTML,
|
||||||
|
|
|
@ -651,8 +651,12 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// then fall through...
|
// then fall through...
|
||||||
|
case NS_KEY_BEFORE_DOWN:
|
||||||
case NS_KEY_DOWN:
|
case NS_KEY_DOWN:
|
||||||
|
case NS_KEY_AFTER_DOWN:
|
||||||
|
case NS_KEY_BEFORE_UP:
|
||||||
case NS_KEY_UP:
|
case NS_KEY_UP:
|
||||||
|
case NS_KEY_AFTER_UP:
|
||||||
{
|
{
|
||||||
nsIContent* content = GetFocusedContent();
|
nsIContent* content = GetFocusedContent();
|
||||||
if (content)
|
if (content)
|
||||||
|
@ -3159,7 +3163,9 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||||
GenerateDragDropEnterExit(presContext, aEvent->AsDragEvent());
|
GenerateDragDropEnterExit(presContext, aEvent->AsDragEvent());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NS_KEY_BEFORE_UP:
|
||||||
case NS_KEY_UP:
|
case NS_KEY_UP:
|
||||||
|
case NS_KEY_AFTER_UP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NS_KEY_PRESS:
|
case NS_KEY_PRESS:
|
||||||
|
|
|
@ -398,6 +398,8 @@ parent:
|
||||||
|
|
||||||
ReplyKeyEvent(WidgetKeyboardEvent event);
|
ReplyKeyEvent(WidgetKeyboardEvent event);
|
||||||
|
|
||||||
|
DispatchAfterKeyboardEvent(WidgetKeyboardEvent event);
|
||||||
|
|
||||||
sync RequestNativeKeyBindings(WidgetKeyboardEvent event)
|
sync RequestNativeKeyBindings(WidgetKeyboardEvent event)
|
||||||
returns (MaybeNativeKeyBinding bindings);
|
returns (MaybeNativeKeyBinding bindings);
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,8 @@
|
||||||
#include "ClientLayerManager.h"
|
#include "ClientLayerManager.h"
|
||||||
#include "LayersLogging.h"
|
#include "LayersLogging.h"
|
||||||
#include "nsIOService.h"
|
#include "nsIOService.h"
|
||||||
|
|
||||||
#include "nsColorPickerProxy.h"
|
#include "nsColorPickerProxy.h"
|
||||||
|
#include "nsPresShell.h"
|
||||||
|
|
||||||
#define BROWSER_ELEMENT_CHILD_SCRIPT \
|
#define BROWSER_ELEMENT_CHILD_SCRIPT \
|
||||||
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
|
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
|
||||||
|
@ -2362,6 +2362,10 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
|
||||||
SendReplyKeyEvent(localEvent);
|
SendReplyKeyEvent(localEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PresShell::BeforeAfterKeyboardEventEnabled()) {
|
||||||
|
SendDispatchAfterKeyboardEvent(localEvent);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "nsIWindowWatcher.h"
|
#include "nsIWindowWatcher.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsPIWindowWatcher.h"
|
#include "nsPIWindowWatcher.h"
|
||||||
|
#include "nsPresShell.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
@ -1463,6 +1464,29 @@ TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& event)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TabParent::RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(mFrameElement, true);
|
||||||
|
|
||||||
|
WidgetKeyboardEvent localEvent(aEvent);
|
||||||
|
localEvent.widget = GetWidget();
|
||||||
|
|
||||||
|
nsIDocument* doc = mFrameElement->OwnerDoc();
|
||||||
|
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
|
||||||
|
NS_ENSURE_TRUE(presShell, true);
|
||||||
|
|
||||||
|
if (mFrameElement &&
|
||||||
|
PresShell::BeforeAfterKeyboardEventEnabled() &&
|
||||||
|
localEvent.message != NS_KEY_PRESS) {
|
||||||
|
nsCOMPtr<nsINode> node(do_QueryInterface(mFrameElement));
|
||||||
|
presShell->DispatchAfterKeyboardEvent(mFrameElement, localEvent,
|
||||||
|
aEvent.mFlags.mDefaultPrevented);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to answer query event using cached text.
|
* Try to answer query event using cached text.
|
||||||
*
|
*
|
||||||
|
|
|
@ -122,6 +122,7 @@ public:
|
||||||
virtual bool RecvMoveFocus(const bool& aForward) MOZ_OVERRIDE;
|
virtual bool RecvMoveFocus(const bool& aForward) MOZ_OVERRIDE;
|
||||||
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) MOZ_OVERRIDE;
|
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) MOZ_OVERRIDE;
|
||||||
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& event);
|
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& event);
|
||||||
|
virtual bool RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& event);
|
||||||
virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* aActor,
|
virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* aActor,
|
||||||
ScrollingBehavior* aScrolling,
|
ScrollingBehavior* aScrolling,
|
||||||
TextureFactoryIdentifier* aFactoryIdentifier,
|
TextureFactoryIdentifier* aFactoryIdentifier,
|
||||||
|
|
|
@ -78,6 +78,7 @@ class nsDisplayList;
|
||||||
class nsDisplayListBuilder;
|
class nsDisplayListBuilder;
|
||||||
class nsPIDOMWindow;
|
class nsPIDOMWindow;
|
||||||
struct nsPoint;
|
struct nsPoint;
|
||||||
|
class nsINode;
|
||||||
struct nsIntPoint;
|
struct nsIntPoint;
|
||||||
struct nsIntRect;
|
struct nsIntRect;
|
||||||
struct nsRect;
|
struct nsRect;
|
||||||
|
@ -139,8 +140,8 @@ typedef struct CapturingContentInfo {
|
||||||
} CapturingContentInfo;
|
} CapturingContentInfo;
|
||||||
|
|
||||||
#define NS_IPRESSHELL_IID \
|
#define NS_IPRESSHELL_IID \
|
||||||
{ 0x42e9a352, 0x76f3, 0x4ba3, \
|
{ 0xa0a4b515, 0x0b91, 0x4f13, \
|
||||||
{ 0x94, 0x0b, 0x78, 0x9e, 0x58, 0x38, 0x73, 0x4f } }
|
{ 0xa0, 0x60, 0x4b, 0xfb, 0x35, 0x00, 0xdc, 0x00 } }
|
||||||
|
|
||||||
// debug VerifyReflow flags
|
// debug VerifyReflow flags
|
||||||
#define VERIFY_REFLOW_ON 0x01
|
#define VERIFY_REFLOW_ON 0x01
|
||||||
|
@ -855,6 +856,13 @@ public:
|
||||||
nsIDOMEvent* aEvent,
|
nsIDOMEvent* aEvent,
|
||||||
nsEventStatus* aStatus) = 0;
|
nsEventStatus* aStatus) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch AfterKeyboardEvent with specific target.
|
||||||
|
*/
|
||||||
|
virtual void DispatchAfterKeyboardEvent(nsINode* aTarget,
|
||||||
|
const mozilla::WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current target event frame from the PresShell
|
* Gets the current target event frame from the PresShell
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "nsPresShell.h"
|
#include "nsPresShell.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
|
#include "mozilla/dom/BeforeAfterKeyboardEvent.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState()
|
#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState()
|
||||||
#include "mozilla/dom/ShadowRoot.h"
|
#include "mozilla/dom/ShadowRoot.h"
|
||||||
|
@ -72,6 +73,8 @@
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsIPageSequenceFrame.h"
|
#include "nsIPageSequenceFrame.h"
|
||||||
|
#include "nsIPermissionManager.h"
|
||||||
|
#include "nsIMozBrowserFrame.h"
|
||||||
#include "nsCaret.h"
|
#include "nsCaret.h"
|
||||||
#include "TouchCaret.h"
|
#include "TouchCaret.h"
|
||||||
#include "SelectionCarets.h"
|
#include "SelectionCarets.h"
|
||||||
|
@ -81,6 +84,7 @@
|
||||||
#include "nsILayoutHistoryState.h"
|
#include "nsILayoutHistoryState.h"
|
||||||
#include "nsILineIterator.h" // for ScrollContentIntoView
|
#include "nsILineIterator.h" // for ScrollContentIntoView
|
||||||
#include "pldhash.h"
|
#include "pldhash.h"
|
||||||
|
#include "mozilla/dom/BeforeAfterKeyboardEventBinding.h"
|
||||||
#include "mozilla/dom/Touch.h"
|
#include "mozilla/dom/Touch.h"
|
||||||
#include "mozilla/dom/PointerEventBinding.h"
|
#include "mozilla/dom/PointerEventBinding.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
|
@ -705,6 +709,7 @@ static uint32_t sNextPresShellId;
|
||||||
static bool sPointerEventEnabled = true;
|
static bool sPointerEventEnabled = true;
|
||||||
static bool sTouchCaretEnabled = false;
|
static bool sTouchCaretEnabled = false;
|
||||||
static bool sSelectionCaretEnabled = false;
|
static bool sSelectionCaretEnabled = false;
|
||||||
|
static bool sBeforeAfterKeyboardEventEnabled = false;
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
PresShell::TouchCaretPrefEnabled()
|
PresShell::TouchCaretPrefEnabled()
|
||||||
|
@ -728,6 +733,18 @@ PresShell::SelectionCaretPrefEnabled()
|
||||||
return sSelectionCaretEnabled;
|
return sSelectionCaretEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
PresShell::BeforeAfterKeyboardEventEnabled()
|
||||||
|
{
|
||||||
|
static bool sInitialized = false;
|
||||||
|
if (!sInitialized) {
|
||||||
|
Preferences::AddBoolVarCache(&sBeforeAfterKeyboardEventEnabled,
|
||||||
|
"dom.beforeAfterKeyboardEvent.enabled");
|
||||||
|
sInitialized = true;
|
||||||
|
}
|
||||||
|
return sBeforeAfterKeyboardEventEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
PresShell::PresShell()
|
PresShell::PresShell()
|
||||||
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
|
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
|
||||||
{
|
{
|
||||||
|
@ -6862,6 +6879,236 @@ private:
|
||||||
nsCOMPtr<nsIContent> mContent;
|
nsCOMPtr<nsIContent> mContent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckPermissionForBeforeAfterKeyboardEvent(Element* aElement)
|
||||||
|
{
|
||||||
|
// An element which is chrome-privileged should be able to handle before
|
||||||
|
// events and after events.
|
||||||
|
nsIPrincipal* principal = aElement->NodePrincipal();
|
||||||
|
if (nsContentUtils::IsSystemPrincipal(principal)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An element which has "before-after-keyboard-event" permission should be
|
||||||
|
// able to handle before events and after events.
|
||||||
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||||
|
uint32_t permission = nsIPermissionManager::DENY_ACTION;
|
||||||
|
if (permMgr) {
|
||||||
|
permMgr->TestPermissionFromPrincipal(principal, "before-after-keyboard-event", &permission);
|
||||||
|
if (permission == nsIPermissionManager::ALLOW_ACTION) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check "embed-apps" permission for later use.
|
||||||
|
permission = nsIPermissionManager::DENY_ACTION;
|
||||||
|
permMgr->TestPermissionFromPrincipal(principal, "embed-apps", &permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An element can handle before events and after events if the following
|
||||||
|
// conditions are met:
|
||||||
|
// 1) <iframe mozbrowser mozapp>
|
||||||
|
// 2) it has "embed-apps" permission.
|
||||||
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame(do_QueryInterface(aElement));
|
||||||
|
if ((permission == nsIPermissionManager::ALLOW_ACTION) &&
|
||||||
|
browserFrame && browserFrame->GetReallyIsApp()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BuildTargetChainForBeforeAfterKeyboardEvent(nsINode* aTarget,
|
||||||
|
nsTArray<nsCOMPtr<Element> >& aChain,
|
||||||
|
bool& aTargetIsIframe)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget));
|
||||||
|
nsCOMPtr<nsPIDOMWindow> window;
|
||||||
|
Element* frameElement;
|
||||||
|
|
||||||
|
// Initialize frameElement.
|
||||||
|
if (content && content->IsHTML(nsGkAtoms::iframe)) {
|
||||||
|
aTargetIsIframe = true;
|
||||||
|
frameElement = aTarget->AsElement();
|
||||||
|
} else {
|
||||||
|
// If event target is not an iframe, dispatch keydown/keyup event to its
|
||||||
|
// window after dispatching before events to its ancestors.
|
||||||
|
aTargetIsIframe = false;
|
||||||
|
|
||||||
|
// And skip the event target and get its parent frame.
|
||||||
|
window = aTarget->OwnerDoc()->GetWindow();
|
||||||
|
if (window) {
|
||||||
|
frameElement = window->GetFrameElementInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check permission for all ancestors and add them into the target chain.
|
||||||
|
while (frameElement) {
|
||||||
|
if (CheckPermissionForBeforeAfterKeyboardEvent(frameElement)) {
|
||||||
|
aChain.AppendElement(frameElement);
|
||||||
|
}
|
||||||
|
window = frameElement->OwnerDoc()->GetWindow();
|
||||||
|
frameElement = window ? window->GetFrameElementInternal() : nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PresShell::DispatchBeforeKeyboardEventInternal(const nsTArray<nsCOMPtr<Element> >& aChain,
|
||||||
|
const WidgetKeyboardEvent& aEvent,
|
||||||
|
size_t& aChainIndex,
|
||||||
|
bool& aDefaultPrevented)
|
||||||
|
{
|
||||||
|
size_t length = aChain.Length();
|
||||||
|
if (!CanDispatchEvent(&aEvent) || !length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t message =
|
||||||
|
(aEvent.message == NS_KEY_DOWN) ? NS_KEY_BEFORE_DOWN : NS_KEY_BEFORE_UP;
|
||||||
|
nsCOMPtr<EventTarget> eventTarget;
|
||||||
|
// Dispatch before events from the outermost element.
|
||||||
|
for (int32_t i = length - 1; i >= 0; i--) {
|
||||||
|
eventTarget = do_QueryInterface(aChain[i]->OwnerDoc()->GetWindow());
|
||||||
|
if (!eventTarget || !CanDispatchEvent(&aEvent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aChainIndex = i;
|
||||||
|
InternalBeforeAfterKeyboardEvent beforeEvent(aEvent.mFlags.mIsTrusted,
|
||||||
|
message, aEvent.widget);
|
||||||
|
beforeEvent.AssignBeforeAfterKeyEventData(aEvent, false);
|
||||||
|
EventDispatcher::Dispatch(eventTarget, mPresContext, &beforeEvent);
|
||||||
|
|
||||||
|
if (beforeEvent.mFlags.mDefaultPrevented) {
|
||||||
|
aDefaultPrevented = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PresShell::DispatchAfterKeyboardEventInternal(const nsTArray<nsCOMPtr<Element> >& aChain,
|
||||||
|
const WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled,
|
||||||
|
size_t aStartOffset)
|
||||||
|
{
|
||||||
|
size_t length = aChain.Length();
|
||||||
|
if (!CanDispatchEvent(&aEvent) || !length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t message =
|
||||||
|
(aEvent.message == NS_KEY_DOWN) ? NS_KEY_AFTER_DOWN : NS_KEY_AFTER_UP;
|
||||||
|
bool embeddedCancelled = aEmbeddedCancelled;
|
||||||
|
nsCOMPtr<EventTarget> eventTarget;
|
||||||
|
// Dispatch after events from the innermost element.
|
||||||
|
for (uint32_t i = aStartOffset; i < length; i++) {
|
||||||
|
eventTarget = do_QueryInterface(aChain[i]->OwnerDoc()->GetWindow());
|
||||||
|
if (!eventTarget || !CanDispatchEvent(&aEvent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalBeforeAfterKeyboardEvent afterEvent(aEvent.mFlags.mIsTrusted,
|
||||||
|
message, aEvent.widget);
|
||||||
|
afterEvent.AssignBeforeAfterKeyEventData(aEvent, false);
|
||||||
|
afterEvent.mEmbeddedCancelled.SetValue(embeddedCancelled);
|
||||||
|
EventDispatcher::Dispatch(eventTarget, mPresContext, &afterEvent);
|
||||||
|
embeddedCancelled = afterEvent.mFlags.mDefaultPrevented;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PresShell::DispatchAfterKeyboardEvent(nsINode* aTarget,
|
||||||
|
const WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aTarget);
|
||||||
|
MOZ_ASSERT(BeforeAfterKeyboardEventEnabled());
|
||||||
|
|
||||||
|
if (NS_WARN_IF(aEvent.message != NS_KEY_DOWN &&
|
||||||
|
aEvent.message != NS_KEY_UP)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build up a target chain. Each item in the chain will receive an after event.
|
||||||
|
nsAutoTArray<nsCOMPtr<Element>, 5> chain;
|
||||||
|
bool targetIsIframe = false;
|
||||||
|
BuildTargetChainForBeforeAfterKeyboardEvent(aTarget, chain, targetIsIframe);
|
||||||
|
DispatchAfterKeyboardEventInternal(chain, aEvent, aEmbeddedCancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PresShell::CanDispatchEvent(const WidgetGUIEvent* aEvent) const
|
||||||
|
{
|
||||||
|
bool rv =
|
||||||
|
mPresContext && !mHaveShutDown && nsContentUtils::IsSafeToRunScript();
|
||||||
|
if (aEvent) {
|
||||||
|
rv &= (aEvent && aEvent->widget && !aEvent->widget->Destroyed());
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PresShell::HandleKeyboardEvent(nsINode* aTarget,
|
||||||
|
WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled,
|
||||||
|
nsEventStatus* aStatus,
|
||||||
|
EventDispatchingCallback* aEventCB)
|
||||||
|
{
|
||||||
|
if (aEvent.message == NS_KEY_PRESS ||
|
||||||
|
!BeforeAfterKeyboardEventEnabled()) {
|
||||||
|
EventDispatcher::Dispatch(aTarget, mPresContext,
|
||||||
|
&aEvent, nullptr, aStatus, aEventCB);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(aTarget);
|
||||||
|
MOZ_ASSERT(aEvent.message == NS_KEY_DOWN || aEvent.message == NS_KEY_UP);
|
||||||
|
|
||||||
|
// Build up a target chain. Each item in the chain will receive a before event.
|
||||||
|
nsAutoTArray<nsCOMPtr<Element>, 5> chain;
|
||||||
|
bool targetIsIframe = false;
|
||||||
|
BuildTargetChainForBeforeAfterKeyboardEvent(aTarget, chain, targetIsIframe);
|
||||||
|
|
||||||
|
// Dispatch before events. If each item in the chain consumes the before
|
||||||
|
// event and doesn't prevent the default action, we will go further to
|
||||||
|
// dispatch the actual key event and after events in the reverse order.
|
||||||
|
// Otherwise, only items which has handled the before event will receive an
|
||||||
|
// after event.
|
||||||
|
size_t chainIndex;
|
||||||
|
bool defaultPrevented = false;
|
||||||
|
DispatchBeforeKeyboardEventInternal(chain, aEvent, chainIndex,
|
||||||
|
defaultPrevented);
|
||||||
|
|
||||||
|
// Dispatch after events to partial items.
|
||||||
|
if (defaultPrevented) {
|
||||||
|
DispatchAfterKeyboardEventInternal(chain, aEvent,
|
||||||
|
aEvent.mFlags.mDefaultPrevented, chainIndex);
|
||||||
|
|
||||||
|
// No need to forward the event to child process.
|
||||||
|
aEvent.mFlags.mNoCrossProcessBoundaryForwarding = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners may kill nsPresContext and nsPresShell.
|
||||||
|
if (!CanDispatchEvent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch actual key event to event target.
|
||||||
|
EventDispatcher::Dispatch(aTarget, mPresContext,
|
||||||
|
&aEvent, nullptr, aStatus, aEventCB);
|
||||||
|
|
||||||
|
// Event listeners may kill nsPresContext and nsPresShell.
|
||||||
|
if (targetIsIframe || !CanDispatchEvent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch after events to all items in the chain.
|
||||||
|
DispatchAfterKeyboardEventInternal(chain, aEvent,
|
||||||
|
aEvent.mFlags.mDefaultPrevented);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PresShell::HandleEvent(nsIFrame* aFrame,
|
PresShell::HandleEvent(nsIFrame* aFrame,
|
||||||
WidgetGUIEvent* aEvent,
|
WidgetGUIEvent* aEvent,
|
||||||
|
@ -7866,6 +8113,9 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
||||||
IMEStateManager::DispatchCompositionEvent(eventTarget,
|
IMEStateManager::DispatchCompositionEvent(eventTarget,
|
||||||
mPresContext, aEvent->AsCompositionEvent(), aStatus,
|
mPresContext, aEvent->AsCompositionEvent(), aStatus,
|
||||||
eventCBPtr);
|
eventCBPtr);
|
||||||
|
} else if (aEvent->mClass == eKeyboardEventClass) {
|
||||||
|
HandleKeyboardEvent(eventTarget, *(aEvent->AsKeyboardEvent()),
|
||||||
|
false, aStatus, eventCBPtr);
|
||||||
} else {
|
} else {
|
||||||
EventDispatcher::Dispatch(eventTarget, mPresContext,
|
EventDispatcher::Dispatch(eventTarget, mPresContext,
|
||||||
aEvent, nullptr, aStatus, eventCBPtr);
|
aEvent, nullptr, aStatus, eventCBPtr);
|
||||||
|
|
|
@ -50,6 +50,7 @@ class nsAutoCauseReflowNotifier;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class CSSStyleSheet;
|
class CSSStyleSheet;
|
||||||
|
class EventDispatchingCallback;
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
// 250ms. This is actually pref-controlled, but we use this value if we fail
|
// 250ms. This is actually pref-controlled, but we use this value if we fail
|
||||||
|
@ -75,6 +76,9 @@ public:
|
||||||
// Selection caret preference
|
// Selection caret preference
|
||||||
static bool SelectionCaretPrefEnabled();
|
static bool SelectionCaretPrefEnabled();
|
||||||
|
|
||||||
|
// BeforeAfterKeyboardEvent preference
|
||||||
|
static bool BeforeAfterKeyboardEventEnabled();
|
||||||
|
|
||||||
void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
|
void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
|
||||||
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
|
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
|
||||||
nsCompatibility aCompatMode);
|
nsCompatibility aCompatMode);
|
||||||
|
@ -369,6 +373,10 @@ public:
|
||||||
|
|
||||||
virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
|
virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot);
|
||||||
|
|
||||||
|
virtual void DispatchAfterKeyboardEvent(nsINode* aTarget,
|
||||||
|
const mozilla::WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled) MOZ_OVERRIDE;
|
||||||
|
|
||||||
void SetNextPaintCompressed() { mNextPaintCompressed = true; }
|
void SetNextPaintCompressed() { mNextPaintCompressed = true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -719,6 +727,24 @@ protected:
|
||||||
|
|
||||||
void EvictTouches();
|
void EvictTouches();
|
||||||
|
|
||||||
|
// Methods for dispatching KeyboardEvent and BeforeAfterKeyboardEvent.
|
||||||
|
void HandleKeyboardEvent(nsINode* aTarget,
|
||||||
|
mozilla::WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled,
|
||||||
|
nsEventStatus* aStatus,
|
||||||
|
mozilla::EventDispatchingCallback* aEventCB);
|
||||||
|
void DispatchBeforeKeyboardEventInternal(
|
||||||
|
const nsTArray<nsCOMPtr<mozilla::dom::Element> >& aChain,
|
||||||
|
const mozilla::WidgetKeyboardEvent& aEvent,
|
||||||
|
size_t& aChainIndex,
|
||||||
|
bool& aDefaultPrevented);
|
||||||
|
void DispatchAfterKeyboardEventInternal(
|
||||||
|
const nsTArray<nsCOMPtr<mozilla::dom::Element> >& aChain,
|
||||||
|
const mozilla::WidgetKeyboardEvent& aEvent,
|
||||||
|
bool aEmbeddedCancelled,
|
||||||
|
size_t aChainIndex = 0);
|
||||||
|
bool CanDispatchEvent(const mozilla::WidgetGUIEvent* aEvent = nullptr) const;
|
||||||
|
|
||||||
// A list of images that are visible or almost visible.
|
// A list of images that are visible or almost visible.
|
||||||
nsTHashtable< nsRefPtrHashKey<nsIImageLoadingContent> > mVisibleImages;
|
nsTHashtable< nsRefPtrHashKey<nsIImageLoadingContent> > mVisibleImages;
|
||||||
|
|
||||||
|
|
|
@ -4347,6 +4347,9 @@ pref("camera.control.low_memory_thresholdMB", 404);
|
||||||
// UDPSocket API
|
// UDPSocket API
|
||||||
pref("dom.udpsocket.enabled", false);
|
pref("dom.udpsocket.enabled", false);
|
||||||
|
|
||||||
|
// Disable before keyboard events and after keyboard events by default.
|
||||||
|
pref("dom.beforeAfterKeyboardEvent.enabled", false);
|
||||||
|
|
||||||
// Experiment: Get TTL from DNS records.
|
// Experiment: Get TTL from DNS records.
|
||||||
// Unset initially (0); Randomly chosen on first run; will remain unchanged
|
// Unset initially (0); Randomly chosen on first run; will remain unchanged
|
||||||
// unless adjusted by the user or experiment ends. Variants defined in
|
// unless adjusted by the user or experiment ends. Variants defined in
|
||||||
|
|
Загрузка…
Ссылка в новой задаче