mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 1330252, try to avoid flooding child process with repeated key events, r=masayuki
--HG-- extra : rebase_source : 53241a14eae10852024d68837d377b91a2f7fbec
This commit is contained in:
parent
0c21611303
commit
cb443e8ff8
@ -383,6 +383,7 @@ TabChild::TabChild(nsIContentChild* aManager,
|
||||
, mDidSetRealShowInfo(false)
|
||||
, mDidLoadURLInit(false)
|
||||
, mIsFreshProcess(false)
|
||||
, mSkipKeyPress(false)
|
||||
, mLayerObserverEpoch(0)
|
||||
#if defined(XP_WIN) && defined(ACCESSIBILITY)
|
||||
, mNativeWindowHandle(0)
|
||||
@ -1778,10 +1779,52 @@ TabChild::RecvNativeSynthesisResponse(const uint64_t& aObserverId,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
// In case handling repeated keys takes much time, we skip firing new ones.
|
||||
bool
|
||||
TabChild::SkipRepeatedKeyEvent(const WidgetKeyboardEvent& aEvent)
|
||||
{
|
||||
if (mRepeatedKeyEventTime.IsNull() ||
|
||||
!aEvent.mIsRepeat ||
|
||||
(aEvent.mMessage != eKeyDown && aEvent.mMessage != eKeyPress)) {
|
||||
mRepeatedKeyEventTime = TimeStamp();
|
||||
mSkipKeyPress = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((aEvent.mMessage == eKeyDown &&
|
||||
(mRepeatedKeyEventTime > aEvent.mTimeStamp)) ||
|
||||
(mSkipKeyPress && (aEvent.mMessage == eKeyPress))) {
|
||||
// If we skip a keydown event, also the following keypress events should be
|
||||
// skipped.
|
||||
mSkipKeyPress |= aEvent.mMessage == eKeyDown;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aEvent.mMessage == eKeyDown) {
|
||||
// If keydown wasn't skipped, nor should the possible following keypress.
|
||||
mRepeatedKeyEventTime = TimeStamp();
|
||||
mSkipKeyPress = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::UpdateRepeatedKeyEventEndTime(const WidgetKeyboardEvent& aEvent)
|
||||
{
|
||||
if (aEvent.mIsRepeat &&
|
||||
(aEvent.mMessage == eKeyDown || aEvent.mMessage == eKeyPress)) {
|
||||
mRepeatedKeyEventTime = TimeStamp::Now();
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
|
||||
const MaybeNativeKeyBinding& aBindings)
|
||||
{
|
||||
if (SkipRepeatedKeyEvent(event)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
AutoCacheNativeKeyCommands autoCache(mPuppetWidget);
|
||||
|
||||
if (event.mMessage == eKeyPress) {
|
||||
@ -1804,6 +1847,10 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
|
||||
// Update the end time of the possible repeated event so that we can skip
|
||||
// some incoming events in case event handling took long time.
|
||||
UpdateRepeatedKeyEventEndTime(localEvent);
|
||||
|
||||
if (event.mMessage == eKeyDown) {
|
||||
mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
@ -747,6 +747,10 @@ private:
|
||||
mUnscaledInnerSize = aSize;
|
||||
}
|
||||
|
||||
bool SkipRepeatedKeyEvent(const WidgetKeyboardEvent& aEvent);
|
||||
|
||||
void UpdateRepeatedKeyEventEndTime(const WidgetKeyboardEvent& aEvent);
|
||||
|
||||
class DelayedDeleteRunnable;
|
||||
|
||||
TextureFactoryIdentifier mTextureFactoryIdentifier;
|
||||
@ -795,6 +799,13 @@ private:
|
||||
bool mDidLoadURLInit;
|
||||
bool mIsFreshProcess;
|
||||
|
||||
bool mSkipKeyPress;
|
||||
|
||||
// Store the end time of the handling of the last repeated keydown/keypress
|
||||
// event so that in case event handling takes time, some repeated events can
|
||||
// be skipped to not flood child process.
|
||||
mozilla::TimeStamp mRepeatedKeyEventTime;
|
||||
|
||||
AutoTArray<bool, NUMBER_OF_AUDIO_CHANNELS> mAudioChannelsActive;
|
||||
|
||||
RefPtr<layers::IAPZCTreeManager> mApzcTreeManager;
|
||||
|
@ -21,6 +21,8 @@ skip-if = !e10s
|
||||
[browser_bug1004814.js]
|
||||
[browser_bug1008941_dismissGeolocationHanger.js]
|
||||
[browser_bug1238427.js]
|
||||
[browser_bug1316330.js]
|
||||
skip-if = !e10s
|
||||
[browser_cancel_keydown_keypress_event.js]
|
||||
support-files =
|
||||
prevent_return_key.html
|
||||
|
54
dom/tests/browser/browser_bug1316330.js
Normal file
54
dom/tests/browser/browser_bug1316330.js
Normal file
@ -0,0 +1,54 @@
|
||||
const URL =
|
||||
"data:text/html,<script>" +
|
||||
"window.focus();" +
|
||||
"var down = 0; var press = 0;" +
|
||||
"onkeydown = function(e) {" +
|
||||
" document.body.setAttribute('data-down', ++down);" +
|
||||
" if (e.keyCode == 'D') while (Date.now() - startTime < 500) {}" +
|
||||
"};" +
|
||||
"onkeypress = function(e) {" +
|
||||
" document.body.setAttribute('data-press', ++press);" +
|
||||
" if (e.charCode == 'P') while (Date.now() - startTime < 500) {}" +
|
||||
"};" +
|
||||
"</script>";
|
||||
|
||||
function createKeyEvent(type, id, repeated) {
|
||||
var code = id.charCodeAt(0);
|
||||
return new KeyboardEvent(type, { keyCode: code, charCode: code, bubbles: true, repeat: repeated });
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// Need to dispatch a DOM Event explicitly via PresShell to get KeyEvent with .repeat = true to
|
||||
// be handled by EventStateManager, which then forwards the event to the child process.
|
||||
var utils = EventUtils._getDOMWindowUtils(window);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "D", false), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "D", false), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "D", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "D", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "D", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "D", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keyup", "D", true), true);
|
||||
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
is(content.document.body.getAttribute("data-down"), "2", "Correct number of events");
|
||||
is(content.document.body.getAttribute("data-press"), "2", "Correct number of events");
|
||||
});
|
||||
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "P", false), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "P", false), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "P", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "P", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keydown", "P", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keypress", "P", true), true);
|
||||
utils.dispatchDOMEventViaPresShell(browser, createKeyEvent("keyup", "P", true), true);
|
||||
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
is(content.document.body.getAttribute("data-down"), "4", "Correct number of events");
|
||||
is(content.document.body.getAttribute("data-press"), "4", "Correct number of events");
|
||||
});
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
Loading…
Reference in New Issue
Block a user