mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Backed out 4 changesets (bug 1137557) for causing intermittent Gij switching_test.js failures.
Backed out changeset ce86cf91f423 (bug 1137557) Backed out changeset 83af10efcd3c (bug 1137557) Backed out changeset e48ed45d1c80 (bug 1137557) Backed out changeset 81e93b60a622 (bug 1137557) CLOSED TREE --HG-- extra : rebase_source : 2bf3467951041be553ab34c45d49c445829d21bb
This commit is contained in:
parent
268566e18f
commit
aeacc8883e
@ -4,7 +4,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/TextEventDispatcher.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
@ -285,11 +284,8 @@ TextInputProcessor::MaybeDispatchKeydownForComposition(
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t consumedFlags = 0;
|
||||
|
||||
result.mResult = KeydownInternal(*aKeyboardEvent, aKeyFlags, false,
|
||||
consumedFlags);
|
||||
result.mDoDefault = !consumedFlags;
|
||||
result.mDoDefault);
|
||||
if (NS_WARN_IF(NS_FAILED(result.mResult))) {
|
||||
result.mCanContinue = false;
|
||||
return result;
|
||||
@ -758,9 +754,9 @@ NS_IMETHODIMP
|
||||
TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent,
|
||||
uint32_t aKeyFlags,
|
||||
uint8_t aOptionalArgc,
|
||||
uint32_t* aConsumedFlags)
|
||||
bool* aDoDefault)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aConsumedFlags, "aConsumedFlags must not be nullptr");
|
||||
MOZ_RELEASE_ASSERT(aDoDefault, "aDoDefault must not be nullptr");
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
|
||||
if (!aOptionalArgc) {
|
||||
aKeyFlags = 0;
|
||||
@ -773,33 +769,16 @@ TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent,
|
||||
if (NS_WARN_IF(!originalKeyEvent)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags);
|
||||
}
|
||||
|
||||
TextEventDispatcher::DispatchTo
|
||||
TextInputProcessor::GetDispatchTo() const
|
||||
{
|
||||
// Support asynchronous tests.
|
||||
if (mForTests) {
|
||||
return gfxPrefs::TestEventsAsyncEnabled() ?
|
||||
TextEventDispatcher::eDispatchToParentProcess :
|
||||
TextEventDispatcher::eDispatchToCurrentProcess;
|
||||
}
|
||||
|
||||
// Otherwise, TextInputProcessor supports only keyboard apps on B2G.
|
||||
// Keyboard apps on B2G doesn't want to dispatch keyboard events to
|
||||
// chrome process. Therefore, this should dispatch key events only in
|
||||
// the current process.
|
||||
return TextEventDispatcher::eDispatchToCurrentProcess;
|
||||
return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aDoDefault);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
uint32_t aKeyFlags,
|
||||
bool aAllowToDispatchKeypress,
|
||||
uint32_t& aConsumedFlags)
|
||||
bool& aDoDefault)
|
||||
{
|
||||
aConsumedFlags = KEYEVENT_NOT_CONSUMED;
|
||||
aDoDefault = false;
|
||||
|
||||
// We shouldn't modify the internal WidgetKeyboardEvent.
|
||||
WidgetKeyboardEvent keyEvent(aKeyboardEvent);
|
||||
@ -808,8 +787,7 @@ TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
return rv;
|
||||
}
|
||||
|
||||
aConsumedFlags = (aKeyFlags & KEY_DEFAULT_PREVENTED) ? KEYDOWN_IS_CONSUMED :
|
||||
KEYEVENT_NOT_CONSUMED;
|
||||
aDoDefault = !(aKeyFlags & KEY_DEFAULT_PREVENTED);
|
||||
|
||||
if (WidgetKeyboardEvent::GetModifierForKeyName(keyEvent.mKeyNameIndex)) {
|
||||
ModifierKeyData modifierKeyData(keyEvent);
|
||||
@ -836,27 +814,19 @@ TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsEventStatus status = aConsumedFlags ? nsEventStatus_eConsumeNoDefault :
|
||||
nsEventStatus_eIgnore;
|
||||
if (!mDispatcher->DispatchKeyboardEvent(NS_KEY_DOWN, keyEvent, status,
|
||||
GetDispatchTo())) {
|
||||
nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
|
||||
nsEventStatus_eConsumeNoDefault;
|
||||
if (!mDispatcher->DispatchKeyboardEvent(NS_KEY_DOWN, keyEvent, status)) {
|
||||
// If keydown event isn't dispatched, we don't need to dispatch keypress
|
||||
// events.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aConsumedFlags |=
|
||||
(status == nsEventStatus_eConsumeNoDefault) ? KEYDOWN_IS_CONSUMED :
|
||||
KEYEVENT_NOT_CONSUMED;
|
||||
|
||||
if (aAllowToDispatchKeypress &&
|
||||
mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status,
|
||||
GetDispatchTo())) {
|
||||
aConsumedFlags |=
|
||||
(status == nsEventStatus_eConsumeNoDefault) ? KEYPRESS_IS_CONSUMED :
|
||||
KEYEVENT_NOT_CONSUMED;
|
||||
if (aAllowToDispatchKeypress) {
|
||||
mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status);
|
||||
}
|
||||
|
||||
aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -920,8 +890,7 @@ TextInputProcessor::KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
|
||||
nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
|
||||
nsEventStatus_eConsumeNoDefault;
|
||||
mDispatcher->DispatchKeyboardEvent(NS_KEY_UP, keyEvent, status,
|
||||
GetDispatchTo());
|
||||
mDispatcher->DispatchKeyboardEvent(NS_KEY_UP, keyEvent, status);
|
||||
aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/TextEventDispatcher.h"
|
||||
#include "mozilla/TextEventDispatcherListener.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsITextInputProcessor.h"
|
||||
@ -18,6 +17,10 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace widget{
|
||||
class TextEventDispatcher;
|
||||
} // namespace widget
|
||||
|
||||
class TextInputProcessor final : public nsITextInputProcessor
|
||||
, public widget::TextEventDispatcherListener
|
||||
{
|
||||
@ -57,11 +60,10 @@ private:
|
||||
nsresult KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
uint32_t aKeyFlags,
|
||||
bool aAllowToDispatchKeypress,
|
||||
uint32_t& aConsumedFlags);
|
||||
bool& aDoDefault);
|
||||
nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
uint32_t aKeyFlags,
|
||||
bool& aDoDefault);
|
||||
TextEventDispatcher::DispatchTo GetDispatchTo() const;
|
||||
nsresult IsValidStateForComposition();
|
||||
void UnlinkFromTextEventDispatcher();
|
||||
nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,
|
||||
|
@ -15,7 +15,7 @@
|
||||
src="data:text/html,<textarea id='textarea' cols='20' rows='4'></textarea>"></iframe><br/>
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
@ -2340,8 +2340,8 @@ function runKeyTests()
|
||||
reset();
|
||||
var doDefaultKeydown = TIP.keydown(keyA);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
|
||||
description + "TIP.keydown(keyA) should return 0x02 because the keypress event should be consumed by the input element");
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyA) should return false because the keypress event should be consumed by the input element");
|
||||
is(events.length, 2,
|
||||
description + "TIP.keydown(keyA) should cause keydown and keypress event");
|
||||
checkKeyAttrs("TIP.keydown(keyA)", events[0],
|
||||
@ -2371,8 +2371,8 @@ function runKeyTests()
|
||||
reset();
|
||||
doDefaultKeydown = TIP.keydown(keyEnter);
|
||||
|
||||
is(doDefaultKeydown, 0,
|
||||
description + "TIP.keydown(keyEnter) should return 0");
|
||||
ok(doDefaultKeydown,
|
||||
description + "TIP.keydown(keyEnter) should return true");
|
||||
is(events.length, 2,
|
||||
description + "TIP.keydown(keyEnter) should cause keydown and keypress event");
|
||||
checkKeyAttrs("TIP.keydown(keyEnter)", events[0],
|
||||
@ -2402,8 +2402,8 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED);
|
||||
doDefaultKeyup = TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYDOWN_IS_CONSUMED,
|
||||
description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) should return 0x01 because it's marked as consumed at dispatching the event");
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) should return false because it's marked as consumed at dispatching the event");
|
||||
ok(!doDefaultKeyup,
|
||||
description + "TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED) should return false because it's marked as consumed at dispatching the event");
|
||||
is(events.length, 2,
|
||||
@ -2423,7 +2423,7 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyABC);
|
||||
doDefaultKeyup = TIP.keyup(keyABC);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyABC) should return false because the keypress events should be consumed by the input element");
|
||||
ok(doDefaultKeyup,
|
||||
description + "TIP.keyup(keyABC) should return true");
|
||||
@ -2450,8 +2450,8 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY);
|
||||
doDefaultKeyup = TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
|
||||
description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return 0x02 because the keypress events should be consumed by the input element");
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return false because the keypress events should be consumed by the input element");
|
||||
ok(doDefaultKeyup,
|
||||
description + "TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return true");
|
||||
is(events.length, 7,
|
||||
@ -2480,8 +2480,8 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyWithModifiers);
|
||||
doDefaultKeyup = TIP.keyup(keyWithModifiers);
|
||||
|
||||
is(doDefaultKeydown, 0,
|
||||
description + "TIP.keydown(keyWithModifiers) should return 0");
|
||||
ok(doDefaultKeydown,
|
||||
description + "TIP.keydown(keyWithModifiers) should return true");
|
||||
ok(doDefaultKeyup,
|
||||
description + "TIP.keyup(keyWithModifiers) should return true");
|
||||
is(events.length, 3,
|
||||
@ -2502,8 +2502,8 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyA);
|
||||
doDefaultKeyup = TIP.keyup(keyA);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYDOWN_IS_CONSUMED,
|
||||
description + "TIP.keydown(keyA) should return 0x01 because keydown event's preventDefault should be called");
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyA) should return false because keydown event's preventDefault should be called");
|
||||
ok(doDefaultKeyup,
|
||||
description + "TIP.keyup(keyA) should return true");
|
||||
is(events.length, 2,
|
||||
@ -2521,8 +2521,8 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyA);
|
||||
doDefaultKeyup = TIP.keyup(keyA);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
|
||||
description + "TIP.keydown(keyA) should return 0x02 because keypress event's preventDefault should be called");
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyA) should return false because keypress event's preventDefault should be called");
|
||||
ok(doDefaultKeyup,
|
||||
description + "TIP.keyup(keyA) should return true");
|
||||
is(events.length, 3,
|
||||
@ -2543,8 +2543,8 @@ function runKeyTests()
|
||||
doDefaultKeydown = TIP.keydown(keyA);
|
||||
doDefaultKeyup = TIP.keyup(keyA);
|
||||
|
||||
is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
|
||||
description + "TIP.keydown(keyA) should return 0x02 because the key event should be consumed by the input element");
|
||||
ok(!doDefaultKeydown,
|
||||
description + "TIP.keydown(keyA) should return false because the key event should be consumed by the input element");
|
||||
ok(!doDefaultKeyup,
|
||||
description + "TIP.keyup(keyA) should return false because keyup event's preventDefault should be called");
|
||||
is(events.length, 3,
|
||||
|
@ -573,7 +573,7 @@ MozInputContext.prototype = {
|
||||
|
||||
switch (msg.name) {
|
||||
case "Keyboard:SendKey:Result:OK":
|
||||
resolver.resolve(true);
|
||||
resolver.resolve();
|
||||
break;
|
||||
case "Keyboard:SendKey:Result:Error":
|
||||
resolver.reject(json.error);
|
||||
@ -596,7 +596,7 @@ MozInputContext.prototype = {
|
||||
break;
|
||||
case "Keyboard:SetComposition:Result:OK": // Fall through.
|
||||
case "Keyboard:EndComposition:Result:OK":
|
||||
resolver.resolve(true);
|
||||
resolver.resolve();
|
||||
break;
|
||||
default:
|
||||
dump("Could not find a handler for " + msg.name);
|
||||
@ -738,79 +738,40 @@ MozInputContext.prototype = {
|
||||
return this.replaceSurroundingText(null, offset, length);
|
||||
},
|
||||
|
||||
sendKey: function ic_sendKey(dictOrKeyCode, charCode, modifiers, repeat) {
|
||||
if (typeof dictOrKeyCode === 'number') {
|
||||
// XXX: modifiers are ignored in this API method.
|
||||
|
||||
return this._sendPromise((resolverId) => {
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
|
||||
contextId: this._contextId,
|
||||
requestId: resolverId,
|
||||
method: 'sendKey',
|
||||
keyCode: dictOrKeyCode,
|
||||
charCode: charCode,
|
||||
repeat: repeat
|
||||
});
|
||||
});
|
||||
} else if (typeof dictOrKeyCode === 'object') {
|
||||
return this._sendPromise((resolverId) => {
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
|
||||
contextId: this._contextId,
|
||||
requestId: resolverId,
|
||||
method: 'sendKey',
|
||||
keyboardEventDict: this._getkeyboardEventDict(dictOrKeyCode)
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// XXX: Should not reach here; implies WebIDL binding error.
|
||||
throw new TypeError('Unknown argument passed.');
|
||||
}
|
||||
},
|
||||
|
||||
keydown: function ic_keydown(dict) {
|
||||
return this._sendPromise((resolverId) => {
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
|
||||
contextId: this._contextId,
|
||||
requestId: resolverId,
|
||||
method: 'keydown',
|
||||
keyboardEventDict: this._getkeyboardEventDict(dict)
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
keyup: function ic_keyup(dict) {
|
||||
return this._sendPromise((resolverId) => {
|
||||
cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SendKey', {
|
||||
contextId: this._contextId,
|
||||
sendKey: function ic_sendKey(keyCode, charCode, modifiers, repeat) {
|
||||
let self = this;
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmmSendAsyncMessageWithKbID(self, 'Keyboard:SendKey', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
method: 'keyup',
|
||||
keyboardEventDict: this._getkeyboardEventDict(dict)
|
||||
keyCode: keyCode,
|
||||
charCode: charCode,
|
||||
modifiers: modifiers,
|
||||
repeat: repeat
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
setComposition: function ic_setComposition(text, cursor, clauses, dict) {
|
||||
setComposition: function ic_setComposition(text, cursor, clauses) {
|
||||
let self = this;
|
||||
return this._sendPromise((resolverId) => {
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmmSendAsyncMessageWithKbID(self, 'Keyboard:SetComposition', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
text: text,
|
||||
cursor: (typeof cursor !== 'undefined') ? cursor : text.length,
|
||||
clauses: clauses || null,
|
||||
keyboardEventDict: this._getkeyboardEventDict(dict)
|
||||
clauses: clauses || null
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
endComposition: function ic_endComposition(text, dict) {
|
||||
endComposition: function ic_endComposition(text) {
|
||||
let self = this;
|
||||
return this._sendPromise((resolverId) => {
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmmSendAsyncMessageWithKbID(self, 'Keyboard:EndComposition', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
text: text || '',
|
||||
keyboardEventDict: this._getkeyboardEventDict(dict)
|
||||
text: text || ''
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -825,43 +786,6 @@ MozInputContext.prototype = {
|
||||
}
|
||||
callback(aResolverId);
|
||||
});
|
||||
},
|
||||
|
||||
// Take a MozInputMethodKeyboardEventDict dict, creates a keyboardEventDict
|
||||
// object that can be sent to forms.js
|
||||
_getkeyboardEventDict: function(dict) {
|
||||
if (typeof dict !== 'object' || !dict.key) {
|
||||
return;
|
||||
}
|
||||
|
||||
var keyboardEventDict = {
|
||||
key: dict.key,
|
||||
code: dict.code,
|
||||
repeat: dict.repeat,
|
||||
flags: 0
|
||||
};
|
||||
|
||||
if (dict.printable) {
|
||||
keyboardEventDict.flags |=
|
||||
Ci.nsITextInputProcessor.KEY_FORCE_PRINTABLE_KEY;
|
||||
}
|
||||
|
||||
if (/^[a-zA-Z0-9]$/.test(dict.key)) {
|
||||
// keyCode must follow the key value in this range;
|
||||
// disregard the keyCode from content.
|
||||
keyboardEventDict.keyCode = dict.key.toUpperCase().charCodeAt(0);
|
||||
} else if (typeof dict.keyCode === 'number') {
|
||||
// Allow keyCode to be specified for other key values.
|
||||
keyboardEventDict.keyCode = dict.keyCode;
|
||||
|
||||
// Allow keyCode to be explicitly set to zero.
|
||||
if (dict.keyCode === 0) {
|
||||
keyboardEventDict.flags |=
|
||||
Ci.nsITextInputProcessor.KEY_KEEP_KEYCODE_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
return keyboardEventDict;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,6 @@ dump("###################################### forms.js loaded\n");
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
let Cu = Components.utils;
|
||||
let Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
@ -19,50 +18,10 @@ XPCOMUtils.defineLazyServiceGetter(Services, "fm",
|
||||
"@mozilla.org/focus-manager;1",
|
||||
"nsIFocusManager");
|
||||
|
||||
/*
|
||||
* A WeakMap to map window to objects keeping it's TextInputProcessor instance.
|
||||
*/
|
||||
let WindowMap = {
|
||||
// WeakMap of <window, object> pairs.
|
||||
_map: null,
|
||||
|
||||
/*
|
||||
* Set the object associated to the window and return it.
|
||||
*/
|
||||
_getObjForWin: function(win) {
|
||||
if (!this._map) {
|
||||
this._map = new WeakMap();
|
||||
}
|
||||
if (this._map.has(win)) {
|
||||
return this._map.get(win);
|
||||
} else {
|
||||
let obj = {
|
||||
tip: null
|
||||
};
|
||||
this._map.set(win, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
},
|
||||
|
||||
getTextInputProcessor: function(win) {
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
let obj = this._getObjForWin(win);
|
||||
let tip = obj.tip
|
||||
|
||||
if (!tip) {
|
||||
tip = obj.tip = Cc["@mozilla.org/text-input-processor;1"]
|
||||
.createInstance(Ci.nsITextInputProcessor);
|
||||
}
|
||||
|
||||
if (!tip.beginInputTransaction(win, textInputProcessorCallback)) {
|
||||
tip = obj.tip = null;
|
||||
}
|
||||
return tip;
|
||||
}
|
||||
};
|
||||
XPCOMUtils.defineLazyGetter(this, "domWindowUtils", function () {
|
||||
return content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
});
|
||||
|
||||
const RESIZE_SCROLL_DELAY = 20;
|
||||
// In content editable node, when there are hidden elements such as <br>, it
|
||||
@ -82,151 +41,6 @@ let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
|
||||
let HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
|
||||
let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement;
|
||||
|
||||
function guessKeyNameFromKeyCode(KeyboardEvent, aKeyCode) {
|
||||
switch (aKeyCode) {
|
||||
case KeyboardEvent.DOM_VK_CANCEL:
|
||||
return "Cancel";
|
||||
case KeyboardEvent.DOM_VK_HELP:
|
||||
return "Help";
|
||||
case KeyboardEvent.DOM_VK_BACK_SPACE:
|
||||
return "Backspace";
|
||||
case KeyboardEvent.DOM_VK_TAB:
|
||||
return "Tab";
|
||||
case KeyboardEvent.DOM_VK_CLEAR:
|
||||
return "Clear";
|
||||
case KeyboardEvent.DOM_VK_RETURN:
|
||||
return "Enter";
|
||||
case KeyboardEvent.DOM_VK_SHIFT:
|
||||
return "Shift";
|
||||
case KeyboardEvent.DOM_VK_CONTROL:
|
||||
return "Control";
|
||||
case KeyboardEvent.DOM_VK_ALT:
|
||||
return "Alt";
|
||||
case KeyboardEvent.DOM_VK_PAUSE:
|
||||
return "Pause";
|
||||
case KeyboardEvent.DOM_VK_EISU:
|
||||
return "Eisu";
|
||||
case KeyboardEvent.DOM_VK_ESCAPE:
|
||||
return "Escape";
|
||||
case KeyboardEvent.DOM_VK_CONVERT:
|
||||
return "Convert";
|
||||
case KeyboardEvent.DOM_VK_NONCONVERT:
|
||||
return "NonConvert";
|
||||
case KeyboardEvent.DOM_VK_ACCEPT:
|
||||
return "Accept";
|
||||
case KeyboardEvent.DOM_VK_MODECHANGE:
|
||||
return "ModeChange";
|
||||
case KeyboardEvent.DOM_VK_PAGE_UP:
|
||||
return "PageUp";
|
||||
case KeyboardEvent.DOM_VK_PAGE_DOWN:
|
||||
return "PageDown";
|
||||
case KeyboardEvent.DOM_VK_END:
|
||||
return "End";
|
||||
case KeyboardEvent.DOM_VK_HOME:
|
||||
return "Home";
|
||||
case KeyboardEvent.DOM_VK_LEFT:
|
||||
return "ArrowLeft";
|
||||
case KeyboardEvent.DOM_VK_UP:
|
||||
return "ArrowUp";
|
||||
case KeyboardEvent.DOM_VK_RIGHT:
|
||||
return "ArrowRight";
|
||||
case KeyboardEvent.DOM_VK_DOWN:
|
||||
return "ArrowDown";
|
||||
case KeyboardEvent.DOM_VK_SELECT:
|
||||
return "Select";
|
||||
case KeyboardEvent.DOM_VK_PRINT:
|
||||
return "Print";
|
||||
case KeyboardEvent.DOM_VK_EXECUTE:
|
||||
return "Execute";
|
||||
case KeyboardEvent.DOM_VK_PRINTSCREEN:
|
||||
return "PrintScreen";
|
||||
case KeyboardEvent.DOM_VK_INSERT:
|
||||
return "Insert";
|
||||
case KeyboardEvent.DOM_VK_DELETE:
|
||||
return "Delete";
|
||||
case KeyboardEvent.DOM_VK_WIN:
|
||||
return "OS";
|
||||
case KeyboardEvent.DOM_VK_CONTEXT_MENU:
|
||||
return "ContextMenu";
|
||||
case KeyboardEvent.DOM_VK_SLEEP:
|
||||
return "Standby";
|
||||
case KeyboardEvent.DOM_VK_F1:
|
||||
return "F1";
|
||||
case KeyboardEvent.DOM_VK_F2:
|
||||
return "F2";
|
||||
case KeyboardEvent.DOM_VK_F3:
|
||||
return "F3";
|
||||
case KeyboardEvent.DOM_VK_F4:
|
||||
return "F4";
|
||||
case KeyboardEvent.DOM_VK_F5:
|
||||
return "F5";
|
||||
case KeyboardEvent.DOM_VK_F6:
|
||||
return "F6";
|
||||
case KeyboardEvent.DOM_VK_F7:
|
||||
return "F7";
|
||||
case KeyboardEvent.DOM_VK_F8:
|
||||
return "F8";
|
||||
case KeyboardEvent.DOM_VK_F9:
|
||||
return "F9";
|
||||
case KeyboardEvent.DOM_VK_F10:
|
||||
return "F10";
|
||||
case KeyboardEvent.DOM_VK_F11:
|
||||
return "F11";
|
||||
case KeyboardEvent.DOM_VK_F12:
|
||||
return "F12";
|
||||
case KeyboardEvent.DOM_VK_F13:
|
||||
return "F13";
|
||||
case KeyboardEvent.DOM_VK_F14:
|
||||
return "F14";
|
||||
case KeyboardEvent.DOM_VK_F15:
|
||||
return "F15";
|
||||
case KeyboardEvent.DOM_VK_F16:
|
||||
return "F16";
|
||||
case KeyboardEvent.DOM_VK_F17:
|
||||
return "F17";
|
||||
case KeyboardEvent.DOM_VK_F18:
|
||||
return "F18";
|
||||
case KeyboardEvent.DOM_VK_F19:
|
||||
return "F19";
|
||||
case KeyboardEvent.DOM_VK_F20:
|
||||
return "F20";
|
||||
case KeyboardEvent.DOM_VK_F21:
|
||||
return "F21";
|
||||
case KeyboardEvent.DOM_VK_F22:
|
||||
return "F22";
|
||||
case KeyboardEvent.DOM_VK_F23:
|
||||
return "F23";
|
||||
case KeyboardEvent.DOM_VK_F24:
|
||||
return "F24";
|
||||
case KeyboardEvent.DOM_VK_NUM_LOCK:
|
||||
return "NumLock";
|
||||
case KeyboardEvent.DOM_VK_SCROLL_LOCK:
|
||||
return "ScrollLock";
|
||||
case KeyboardEvent.DOM_VK_VOLUME_MUTE:
|
||||
return "VolumeMute";
|
||||
case KeyboardEvent.DOM_VK_VOLUME_DOWN:
|
||||
return "VolumeDown";
|
||||
case KeyboardEvent.DOM_VK_VOLUME_UP:
|
||||
return "VolumeUp";
|
||||
case KeyboardEvent.DOM_VK_META:
|
||||
return "Meta";
|
||||
case KeyboardEvent.DOM_VK_ALTGR:
|
||||
return "AltGraph";
|
||||
case KeyboardEvent.DOM_VK_ATTN:
|
||||
return "Attn";
|
||||
case KeyboardEvent.DOM_VK_CRSEL:
|
||||
return "CrSel";
|
||||
case KeyboardEvent.DOM_VK_EXSEL:
|
||||
return "ExSel";
|
||||
case KeyboardEvent.DOM_VK_EREOF:
|
||||
return "EraseEof";
|
||||
case KeyboardEvent.DOM_VK_PLAY:
|
||||
return "Play";
|
||||
default:
|
||||
return "Unidentified";
|
||||
}
|
||||
}
|
||||
|
||||
let FormVisibility = {
|
||||
/**
|
||||
* Searches upwards in the DOM for an element that has been scrolled.
|
||||
@ -370,41 +184,6 @@ let FormVisibility = {
|
||||
}
|
||||
};
|
||||
|
||||
// This object implements nsITextInputProcessorCallback
|
||||
let textInputProcessorCallback = {
|
||||
onNotify: function(aTextInputProcessor, aNotification) {
|
||||
try {
|
||||
switch (aNotification.type) {
|
||||
case "request-to-commit":
|
||||
// TODO: Send a notification through asyncMessage to the keyboard here.
|
||||
aTextInputProcessor.commitComposition();
|
||||
|
||||
break;
|
||||
case "request-to-cancel":
|
||||
// TODO: Send a notification through asyncMessage to the keyboard here.
|
||||
aTextInputProcessor.cancelComposition();
|
||||
|
||||
break;
|
||||
|
||||
case "notify-detached":
|
||||
// TODO: Send a notification through asyncMessage to the keyboard here.
|
||||
break;
|
||||
|
||||
// TODO: Manage _focusedElement for text input from here instead.
|
||||
// (except for <select> which will be need to handled elsewhere)
|
||||
case "notify-focus":
|
||||
break;
|
||||
|
||||
case "notify-blur":
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
let FormAssistant = {
|
||||
init: function fa_init() {
|
||||
addEventListener("focus", this, true, false);
|
||||
@ -653,7 +432,7 @@ let FormAssistant = {
|
||||
break;
|
||||
|
||||
case "keydown":
|
||||
if (!this.focusedElement || this._editing) {
|
||||
if (!this.focusedElement) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -661,7 +440,7 @@ let FormAssistant = {
|
||||
break;
|
||||
|
||||
case "keyup":
|
||||
if (!this.focusedElement || this._editing) {
|
||||
if (!this.focusedElement) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -723,132 +502,34 @@ let FormAssistant = {
|
||||
case "Forms:Input:SendKey":
|
||||
CompositionManager.endComposition('');
|
||||
|
||||
let win = target.ownerDocument.defaultView;
|
||||
let tip = WindowMap.getTextInputProcessor(win);
|
||||
if (!tip) {
|
||||
if (json.requestId) {
|
||||
sendAsyncMessage("Forms:SendKey:Result:Error", {
|
||||
requestId: json.requestId,
|
||||
error: "Unable to start input transaction."
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
let flags = domWindowUtils.KEY_FLAG_NOT_SYNTHESIZED_FOR_TESTS;
|
||||
this._editing = true;
|
||||
let doKeypress = domWindowUtils.sendKeyEvent('keydown', json.keyCode,
|
||||
json.charCode, json.modifiers, flags);
|
||||
if (doKeypress) {
|
||||
domWindowUtils.sendKeyEvent('keypress', json.keyCode,
|
||||
json.charCode, json.modifiers, flags);
|
||||
}
|
||||
|
||||
// If we receive a keyboardEventDict from json, that means the user
|
||||
// is calling the method with the new arguments.
|
||||
// Otherwise, we would have to construct our own keyboardEventDict
|
||||
// based on legacy values we have received.
|
||||
let keyboardEventDict = json.keyboardEventDict;
|
||||
let flags = 0;
|
||||
|
||||
if (keyboardEventDict) {
|
||||
if ('flags' in keyboardEventDict) {
|
||||
flags = keyboardEventDict.flags;
|
||||
}
|
||||
} else {
|
||||
// The naive way to figure out if the key to dispatch is printable.
|
||||
let printable = !!json.charCode;
|
||||
|
||||
// For printable keys, the value should be the actual character.
|
||||
// For non-printable keys, it should be a value in the D3E spec.
|
||||
// Here we make some educated guess for it.
|
||||
let key = printable ?
|
||||
String.fromCharCode(json.charCode) :
|
||||
guessKeyNameFromKeyCode(win.KeyboardEvent, json.keyCode);
|
||||
|
||||
// keyCode from content is only respected when the key is not an
|
||||
// an alphanumeric character. We also ask TextInputProcessor not to
|
||||
// infer this value for non-printable keys to keep the original
|
||||
// behavior.
|
||||
let keyCode = (printable && /^[a-zA-Z0-9]$/.test(key)) ?
|
||||
key.toUpperCase().charCodeAt(0) :
|
||||
json.keyCode;
|
||||
|
||||
keyboardEventDict = {
|
||||
key: key,
|
||||
keyCode: keyCode,
|
||||
// We don't have any information to tell the virtual key the
|
||||
// user have interacted with.
|
||||
code: "",
|
||||
// We do not have the information to infer location of the virtual key
|
||||
// either (and we would need TextInputProcessor not to compute it).
|
||||
location: 0,
|
||||
// This indicates the key is triggered for repeats.
|
||||
repeat: json.repeat
|
||||
};
|
||||
|
||||
flags = tip.KEY_KEEP_KEY_LOCATION_STANDARD;
|
||||
if (!printable) {
|
||||
flags |= tip.KEY_NON_PRINTABLE_KEY;
|
||||
}
|
||||
if (!keyboardEventDict.keyCode) {
|
||||
flags |= tip.KEY_KEEP_KEYCODE_ZERO;
|
||||
}
|
||||
if(!json.repeat) {
|
||||
domWindowUtils.sendKeyEvent('keyup', json.keyCode,
|
||||
json.charCode, json.modifiers, flags);
|
||||
}
|
||||
|
||||
let keyboardEvent = new win.KeyboardEvent("", keyboardEventDict);
|
||||
this._editing = false;
|
||||
|
||||
let keydownDefaultPrevented = false;
|
||||
try {
|
||||
switch (json.method) {
|
||||
case 'sendKey': {
|
||||
let consumedFlags = tip.keydown(keyboardEvent, flags);
|
||||
keydownDefaultPrevented =
|
||||
!!(tip.KEYDOWN_IS_CONSUMED & consumedFlags);
|
||||
if (!keyboardEventDict.repeat) {
|
||||
tip.keyup(keyboardEvent, flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'keydown': {
|
||||
let consumedFlags = tip.keydown(keyboardEvent, flags);
|
||||
keydownDefaultPrevented =
|
||||
!!(tip.KEYDOWN_IS_CONSUMED & consumedFlags);
|
||||
break;
|
||||
}
|
||||
case 'keyup': {
|
||||
tip.keyup(keyboardEvent, flags);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
dump("forms.js:" + err.toString() + "\n");
|
||||
|
||||
if (json.requestId) {
|
||||
if (err instanceof Ci.nsIException &&
|
||||
err.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
|
||||
sendAsyncMessage("Forms:SendKey:Result:Error", {
|
||||
requestId: json.requestId,
|
||||
error: "The values specified are illegal."
|
||||
});
|
||||
} else {
|
||||
sendAsyncMessage("Forms:SendKey:Result:Error", {
|
||||
requestId: json.requestId,
|
||||
error: "Unable to type into destroyed input."
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
if (json.requestId && doKeypress) {
|
||||
sendAsyncMessage("Forms:SendKey:Result:OK", {
|
||||
requestId: json.requestId,
|
||||
selectioninfo: this.getSelectionInfo()
|
||||
});
|
||||
}
|
||||
|
||||
if (json.requestId) {
|
||||
if (keydownDefaultPrevented) {
|
||||
sendAsyncMessage("Forms:SendKey:Result:Error", {
|
||||
requestId: json.requestId,
|
||||
error: "Key event(s) was cancelled."
|
||||
});
|
||||
} else {
|
||||
sendAsyncMessage("Forms:SendKey:Result:OK", {
|
||||
requestId: json.requestId,
|
||||
selectioninfo: this.getSelectionInfo()
|
||||
});
|
||||
}
|
||||
else if (json.requestId && !doKeypress) {
|
||||
sendAsyncMessage("Forms:SendKey:Result:Error", {
|
||||
requestId: json.requestId,
|
||||
error: "Keydown event got canceled"
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Forms:Select:Choice":
|
||||
@ -961,7 +642,7 @@ let FormAssistant = {
|
||||
|
||||
case "Forms:SetComposition": {
|
||||
CompositionManager.setComposition(target, json.text, json.cursor,
|
||||
json.clauses, json.keyboardEventDict);
|
||||
json.clauses);
|
||||
sendAsyncMessage("Forms:SetComposition:Result:OK", {
|
||||
requestId: json.requestId,
|
||||
selectioninfo: this.getSelectionInfo()
|
||||
@ -970,7 +651,7 @@ let FormAssistant = {
|
||||
}
|
||||
|
||||
case "Forms:EndComposition": {
|
||||
CompositionManager.endComposition(json.text, json.keyboardEventDict);
|
||||
CompositionManager.endComposition(json.text);
|
||||
sendAsyncMessage("Forms:EndComposition:Result:OK", {
|
||||
requestId: json.requestId,
|
||||
selectioninfo: this.getSelectionInfo()
|
||||
@ -1489,8 +1170,7 @@ function replaceSurroundingText(element, text, offset, length) {
|
||||
|
||||
let CompositionManager = {
|
||||
_isStarted: false,
|
||||
_tip: null,
|
||||
_KeyboardEventForWin: null,
|
||||
_textInputProcessor: null,
|
||||
_clauseAttrMap: {
|
||||
'raw-input':
|
||||
Ci.nsITextInputProcessor.ATTR_RAW_CLAUSE,
|
||||
@ -1502,7 +1182,35 @@ let CompositionManager = {
|
||||
Ci.nsITextInputProcessor.ATTR_SELECTED_CLAUSE
|
||||
},
|
||||
|
||||
setComposition: function cm_setComposition(element, text, cursor, clauses, dict) {
|
||||
_callback: function cm_callback(aTIP, aNotification)
|
||||
{
|
||||
try {
|
||||
switch (aNotification.type) {
|
||||
case "request-to-commit":
|
||||
aTIP.commitComposition();
|
||||
break;
|
||||
case "request-to-cancel":
|
||||
aTIP.cancelComposition();
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
_prepareTextInputProcessor: function cm_prepareTextInputProcessor(aWindow)
|
||||
{
|
||||
if (!this._textInputProcessor) {
|
||||
this._textInputProcessor =
|
||||
Cc["@mozilla.org/text-input-processor;1"].
|
||||
createInstance(Ci.nsITextInputProcessor);
|
||||
}
|
||||
return this._textInputProcessor.beginInputTransaction(aWindow,
|
||||
this._callback);
|
||||
},
|
||||
|
||||
setComposition: function cm_setComposition(element, text, cursor, clauses) {
|
||||
// Check parameters.
|
||||
if (!element) {
|
||||
return;
|
||||
@ -1540,57 +1248,30 @@ let CompositionManager = {
|
||||
}
|
||||
|
||||
let win = element.ownerDocument.defaultView;
|
||||
let tip = WindowMap.getTextInputProcessor(win);
|
||||
if (!tip) {
|
||||
if (!this._prepareTextInputProcessor(win)) {
|
||||
return;
|
||||
}
|
||||
// Update the composing text.
|
||||
tip.setPendingCompositionString(text);
|
||||
this._textInputProcessor.setPendingCompositionString(text);
|
||||
for (var i = 0; i < clauseLens.length; i++) {
|
||||
if (!clauseLens[i]) {
|
||||
continue;
|
||||
}
|
||||
tip.appendClauseToPendingComposition(clauseLens[i], clauseAttrs[i]);
|
||||
this._textInputProcessor.appendClauseToPendingComposition(clauseLens[i],
|
||||
clauseAttrs[i]);
|
||||
}
|
||||
if (cursor >= 0) {
|
||||
tip.setCaretInPendingComposition(cursor);
|
||||
}
|
||||
|
||||
if (!dict) {
|
||||
this._isStarted = tip.flushPendingComposition();
|
||||
} else {
|
||||
let keyboardEvent = new win.KeyboardEvent("", dict);
|
||||
let flags = dict.flags;
|
||||
this._isStarted = tip.flushPendingComposition(keyboardEvent, flags);
|
||||
}
|
||||
|
||||
if (this._isStarted) {
|
||||
this._tip = tip;
|
||||
this._KeyboardEventForWin = win.KeyboardEvent;
|
||||
this._textInputProcessor.setCaretInPendingComposition(cursor);
|
||||
}
|
||||
this._isStarted = this._textInputProcessor.flushPendingComposition();
|
||||
},
|
||||
|
||||
endComposition: function cm_endComposition(text, dict) {
|
||||
endComposition: function cm_endComposition(text) {
|
||||
if (!this._isStarted) {
|
||||
return;
|
||||
}
|
||||
let tip = this._tip;
|
||||
if (!tip) {
|
||||
return;
|
||||
}
|
||||
|
||||
text = text || "";
|
||||
if (!dict) {
|
||||
tip.commitCompositionWith(text);
|
||||
} else {
|
||||
let keyboardEvent = new this._KeyboardEventForWin("", dict);
|
||||
let flags = dict.flags;
|
||||
tip.commitCompositionWith(text, keyboardEvent, flags);
|
||||
}
|
||||
|
||||
this._textInputProcessor.commitCompositionWith(text ? text : "");
|
||||
this._isStarted = false;
|
||||
this._tip = null;
|
||||
this._KeyboardEventForWin = null;
|
||||
},
|
||||
|
||||
// Composition ends due to external actions.
|
||||
@ -1600,7 +1281,5 @@ let CompositionManager = {
|
||||
}
|
||||
|
||||
this._isStarted = false;
|
||||
this._tip = null;
|
||||
this._KeyboardEventForWin = null;
|
||||
}
|
||||
};
|
||||
|
@ -26,4 +26,3 @@ support-files =
|
||||
[test_two_inputs.html]
|
||||
[test_two_selects.html]
|
||||
[test_unload.html]
|
||||
[test_bug1137557.html]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -254,7 +254,7 @@ interface nsITextInputProcessorCallback;
|
||||
* TIP.keyup(leftShift);
|
||||
*/
|
||||
|
||||
[scriptable, builtinclass, uuid(581f6619-76ed-478c-905d-b8e6553a714a)]
|
||||
[scriptable, builtinclass, uuid(6617a9f6-3e16-4086-9e1e-c8a6c5d505c7)]
|
||||
interface nsITextInputProcessor : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -489,12 +489,6 @@ interface nsITextInputProcessor : nsISupports
|
||||
// or emulating legacy API behavior.
|
||||
const unsigned long KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT = 0x00000020;
|
||||
|
||||
// These values can be used to do bitwise operation with the return value of
|
||||
// the keydown() method.
|
||||
const unsigned long KEYEVENT_NOT_CONSUMED = 0x00000000;
|
||||
const unsigned long KEYDOWN_IS_CONSUMED = 0x00000001;
|
||||
const unsigned long KEYPRESS_IS_CONSUMED = 0x00000002;
|
||||
|
||||
/**
|
||||
* keydown() may dispatch a keydown event and some keypress events if
|
||||
* preceding keydown event isn't consumed and they are necessary.
|
||||
@ -535,20 +529,13 @@ interface nsITextInputProcessor : nsISupports
|
||||
* each instance and set automatically.
|
||||
* @param aKeyFlags Special flags. The values can be some of KEY_*
|
||||
* constants.
|
||||
* @return KEYEVENT_NOT_CONSUMED, if the keydown event nor
|
||||
* the following keypress event(s) are consumed.
|
||||
* KEYDOWN_IS_CONSUMED, if the keydown event is
|
||||
* consumed. No keypress event will be dispatched in
|
||||
* this case.
|
||||
* KEYPRESS_IS_CONSUMED, if the keypress event(s) is
|
||||
* consumed when dispatched.
|
||||
* Note that keypress event is always consumed by
|
||||
* native code for the printable keys (indicating the
|
||||
* default action has been taken).
|
||||
* @return true if neither the keydown event or following
|
||||
* keypress events is *not* consumed.
|
||||
* Otherwise, i.e., preventDefault() is called, false.
|
||||
*/
|
||||
[optional_argc]
|
||||
unsigned long keydown(in nsIDOMKeyEvent aKeyboardEvent,
|
||||
[optional] in unsigned long aKeyFlags);
|
||||
boolean keydown(in nsIDOMKeyEvent aKeyboardEvent,
|
||||
[optional] in unsigned long aKeyFlags);
|
||||
|
||||
/**
|
||||
* Similar to keydown(), but this dispatches only a keyup event.
|
||||
|
@ -192,54 +192,17 @@ interface MozInputContext: EventTarget {
|
||||
attribute EventHandler onsurroundingtextchange;
|
||||
|
||||
/*
|
||||
* Send a string/character with its key events. There are two ways of invocating
|
||||
* the method for backward compability purpose.
|
||||
*
|
||||
* (1) The recommended way, allow specifying DOM level 3 properties like |code|.
|
||||
* @param dictOrKeyCode See MozInputMethodKeyboardEventDict.
|
||||
* @param charCode disregarded
|
||||
* @param modifiers disregarded
|
||||
* @param repeat disregarded
|
||||
*
|
||||
* (2) Deprecated, reserved for backward compability.
|
||||
* @param dictOrKeyCode keyCode of the key to send, should be one of the DOM_VK_ value in KeyboardEvent.
|
||||
* @param charCode charCode of the character, should be 0 for non-printable keys.
|
||||
* @param modifiers this paramater is no longer honored.
|
||||
* @param repeat indicates whether a key would be sent repeatedly.
|
||||
*
|
||||
* @return A promise. Resolve to true if succeeds.
|
||||
* Rejects to a string indicating the error.
|
||||
*
|
||||
* Note that, if you want to send a key n times repeatedly, make sure set
|
||||
* parameter repeat to true and invoke sendKey n times, and invoke keyup
|
||||
* after the end of the input.
|
||||
*/
|
||||
Promise<boolean> sendKey((MozInputMethodRequiredKeyboardEventDict or long) dictOrKeyCode,
|
||||
optional long charCode,
|
||||
optional long modifiers,
|
||||
optional boolean repeat);
|
||||
|
||||
/*
|
||||
* Send a string/character with keydown, and keypress events.
|
||||
* keyup should be called afterwards to ensure properly sequence.
|
||||
*
|
||||
* @param dict See MozInputMethodKeyboardEventDict.
|
||||
*
|
||||
* @return A promise. Resolve to true if succeeds.
|
||||
* Rejects to a string indicating the error.
|
||||
*/
|
||||
Promise<boolean> keydown(MozInputMethodRequiredKeyboardEventDict dict);
|
||||
|
||||
/*
|
||||
* Send a keyup event. keydown should be called first to ensure properly sequence.
|
||||
*
|
||||
* @param dict See MozInputMethodKeyboardEventDict.
|
||||
*
|
||||
* @return A promise. Resolve to true if succeeds.
|
||||
* Rejects to a string indicating the error.
|
||||
*
|
||||
*/
|
||||
Promise<boolean> keyup(MozInputMethodRequiredKeyboardEventDict dict);
|
||||
* send a character with its key events.
|
||||
* @param modifiers see http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/base/nsIDOMWindowUtils.idl#206
|
||||
* @param repeat indicates whether a key would be sent repeatedly.
|
||||
* @return true if succeeds. Otherwise false if the input context becomes void.
|
||||
* Alternative: sendKey(KeyboardEvent event), but we will likely
|
||||
* waste memory for creating the KeyboardEvent object.
|
||||
* Note that, if you want to send a key n times repeatedly, make sure set
|
||||
* parameter repeat to true and invoke sendKey n-1 times, and then set
|
||||
* repeat to false in the last invoke.
|
||||
*/
|
||||
Promise<boolean> sendKey(long keyCode, long charCode, long modifiers, optional boolean repeat);
|
||||
|
||||
/*
|
||||
* Set current composing text. This method will start composition or update
|
||||
@ -255,11 +218,7 @@ interface MozInputContext: EventTarget {
|
||||
* cursor will be positioned after the composition text.
|
||||
* @param clauses The array of composition clause information. If not set,
|
||||
* only one clause is supported.
|
||||
* @param dict The properties of the keyboard event that cause the composition
|
||||
* to set. keydown or keyup event will be fired if it's necessary.
|
||||
* For compatibility, we recommend that you should always set this argument
|
||||
* if it's caused by a key operation.
|
||||
*
|
||||
*
|
||||
* The composing text, which is shown with underlined style to distinguish
|
||||
* from the existing text, is used to compose non-ASCII characters from
|
||||
* keystrokes, e.g. Pinyin or Hiragana. The composing text is the
|
||||
@ -272,10 +231,9 @@ interface MozInputContext: EventTarget {
|
||||
* To finish composition and commit text to current input field, an IME
|
||||
* should call |endComposition|.
|
||||
*/
|
||||
Promise<boolean> setComposition(DOMString text,
|
||||
optional long cursor,
|
||||
optional sequence<CompositionClauseParameters> clauses,
|
||||
optional MozInputMethodKeyboardEventDict dict);
|
||||
// XXXbz what is this promise resolved with?
|
||||
Promise<any> setComposition(DOMString text, optional long cursor,
|
||||
optional sequence<CompositionClauseParameters> clauses);
|
||||
|
||||
/*
|
||||
* End composition, clear the composing text and commit given text to
|
||||
@ -283,10 +241,6 @@ interface MozInputContext: EventTarget {
|
||||
* position.
|
||||
* @param text The text to commited before cursor position. If empty string
|
||||
* is given, no text will be committed.
|
||||
* @param dict The properties of the keyboard event that cause the composition
|
||||
* to end. keydown or keyup event will be fired if it's necessary.
|
||||
* For compatibility, we recommend that you should always set this argument
|
||||
* if it's caused by a key operation.
|
||||
*
|
||||
* Note that composition always ends automatically with nothing to commit if
|
||||
* the composition does not explicitly end by calling |endComposition|, but
|
||||
@ -294,8 +248,8 @@ interface MozInputContext: EventTarget {
|
||||
* |replaceSurroundingText|, |deleteSurroundingText|, user moving the
|
||||
* cursor, changing the focus, etc.
|
||||
*/
|
||||
Promise<boolean> endComposition(optional DOMString text,
|
||||
optional MozInputMethodKeyboardEventDict dict);
|
||||
// XXXbz what is this promise resolved with?
|
||||
Promise<any> endComposition(optional DOMString text);
|
||||
};
|
||||
|
||||
enum CompositionClauseSelectionType {
|
||||
@ -309,66 +263,3 @@ dictionary CompositionClauseParameters {
|
||||
DOMString selectionType = "raw-input";
|
||||
long length;
|
||||
};
|
||||
|
||||
/*
|
||||
* A MozInputMethodKeyboardEventDictBase contains the following properties,
|
||||
* indicating the properties of the keyboard event caused.
|
||||
*
|
||||
* This is the base dictionary type for us to create two child types that could
|
||||
* be used as argument type in two types of methods, as WebIDL parser required.
|
||||
*
|
||||
*/
|
||||
dictionary MozInputMethodKeyboardEventDictBase {
|
||||
/*
|
||||
* String/character to output, or a registered name of non-printable key.
|
||||
* (To be defined in the inheriting dictionary types.)
|
||||
*/
|
||||
// DOMString key;
|
||||
/*
|
||||
* String/char indicating the virtual hardware key pressed. Optional.
|
||||
* Must be a value defined in
|
||||
* http://www.w3.org/TR/DOM-Level-3-Events-code/#keyboard-chording-virtual
|
||||
* If your keyboard app emulates physical keyboard layout, this value should
|
||||
* not be empty string. Otherwise, it should be empty string.
|
||||
*/
|
||||
DOMString code = "";
|
||||
/*
|
||||
* keyCode of the keyboard event. Optional.
|
||||
* To be disregarded if |key| is an alphanumeric character.
|
||||
* If the key causes inputting a character and if your keyboard app emulates
|
||||
* a physical keyboard layout, this value should be same as the value used
|
||||
* by Firefox for desktop. If the key causes inputting an ASCII character
|
||||
* but if your keyboard app doesn't emulate any physical keyboard layouts,
|
||||
* the value should be proper value for the key value.
|
||||
*/
|
||||
long? keyCode;
|
||||
/*
|
||||
* Indicates whether a key would be sent repeatedly. Optional.
|
||||
*/
|
||||
boolean repeat = false;
|
||||
/*
|
||||
* Optional. True if |key| property is explicitly referring to a printable key.
|
||||
* When this is set, key will be printable even if the |key| value matches any
|
||||
* of the registered name of non-printable keys.
|
||||
*/
|
||||
boolean printable = false;
|
||||
};
|
||||
|
||||
/*
|
||||
* For methods like setComposition() and endComposition(), the optional
|
||||
* dictionary type argument is really optional when all of it's property
|
||||
* are optional.
|
||||
* This dictionary type is used to denote that argument.
|
||||
*/
|
||||
dictionary MozInputMethodKeyboardEventDict : MozInputMethodKeyboardEventDictBase {
|
||||
DOMString? key;
|
||||
};
|
||||
|
||||
/*
|
||||
* For methods like keydown() and keyup(), the dictionary type argument is
|
||||
* considered required only if at least one of it's property is required.
|
||||
* This dictionary type is used to denote that argument.
|
||||
*/
|
||||
dictionary MozInputMethodRequiredKeyboardEventDict : MozInputMethodKeyboardEventDictBase {
|
||||
required DOMString key;
|
||||
};
|
||||
|
@ -140,34 +140,16 @@ nsresult
|
||||
TextEventDispatcher::DispatchEvent(nsIWidget* aWidget,
|
||||
WidgetGUIEvent& aEvent,
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
MOZ_ASSERT(!aEvent.AsInputEvent(), "Use DispatchInputEvent()");
|
||||
|
||||
nsRefPtr<TextEventDispatcher> kungFuDeathGrip(this);
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
mDispatchingEvent++;
|
||||
nsresult rv = widget->DispatchEvent(&aEvent, aStatus);
|
||||
mDispatchingEvent--;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TextEventDispatcher::DispatchInputEvent(nsIWidget* aWidget,
|
||||
WidgetInputEvent& aEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo)
|
||||
{
|
||||
nsRefPtr<TextEventDispatcher> kungFuDeathGrip(this);
|
||||
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||
mDispatchingEvent++;
|
||||
|
||||
// If the event is dispatched via nsIWidget::DispatchInputEvent(), it
|
||||
// sends the event to the parent process first since APZ needs to handle it
|
||||
// first. However, some callers (e.g., keyboard apps on B2G and tests
|
||||
// expecting synchronous dispatch) don't want this to do that.
|
||||
nsresult rv = NS_OK;
|
||||
if (aDispatchTo == eDispatchToParentProcess) {
|
||||
aStatus = widget->DispatchInputEvent(&aEvent);
|
||||
if (aEvent.AsInputEvent() &&
|
||||
(!aEvent.mFlags.mIsSynthesizedForTests || gfxPrefs::TestEventsAsyncEnabled()))
|
||||
{
|
||||
aStatus = widget->DispatchInputEvent(aEvent.AsInputEvent());
|
||||
} else {
|
||||
rv = widget->DispatchEvent(&aEvent, aStatus);
|
||||
}
|
||||
@ -304,11 +286,9 @@ bool
|
||||
TextEventDispatcher::DispatchKeyboardEvent(
|
||||
uint32_t aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo)
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus,
|
||||
aDispatchTo);
|
||||
return DispatchKeyboardEventInternal(aMessage, aKeyboardEvent, aStatus);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -316,7 +296,6 @@ TextEventDispatcher::DispatchKeyboardEventInternal(
|
||||
uint32_t aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo,
|
||||
uint32_t aIndexOfKeypress)
|
||||
{
|
||||
MOZ_ASSERT(aMessage == NS_KEY_DOWN || aMessage == NS_KEY_UP ||
|
||||
@ -395,15 +374,14 @@ TextEventDispatcher::DispatchKeyboardEventInternal(
|
||||
keyEvent.mPluginEvent.Clear();
|
||||
// TODO: Manage mUniqueId here.
|
||||
|
||||
DispatchInputEvent(mWidget, keyEvent, aStatus, aDispatchTo);
|
||||
DispatchEvent(mWidget, keyEvent, aStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TextEventDispatcher::MaybeDispatchKeypressEvents(
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo)
|
||||
nsEventStatus& aStatus)
|
||||
{
|
||||
// If the key event was consumed, keypress event shouldn't be fired.
|
||||
if (aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
@ -423,7 +401,7 @@ TextEventDispatcher::MaybeDispatchKeypressEvents(
|
||||
for (size_t i = 0; i < keypressCount; i++) {
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
if (!DispatchKeyboardEventInternal(NS_KEY_PRESS, aKeyboardEvent,
|
||||
aStatus, aDispatchTo, i)) {
|
||||
aStatus, i)) {
|
||||
// The widget must have been gone.
|
||||
break;
|
||||
}
|
||||
|
@ -180,26 +180,6 @@ public:
|
||||
*/
|
||||
nsresult NotifyIME(const IMENotification& aIMENotification);
|
||||
|
||||
|
||||
/**
|
||||
* DispatchTo indicates whether the event may be dispatched to its parent
|
||||
* process first (if there is) or not. If the event is dispatched to the
|
||||
* parent process, APZ will handle it first. Otherwise, the event won't be
|
||||
* handled by APZ if it's in a child process.
|
||||
*/
|
||||
enum DispatchTo
|
||||
{
|
||||
// The event may be dispatched to its parent process if there is a parent.
|
||||
// In such case, the event will be handled asynchronously. Additionally,
|
||||
// the event may be sent to its child process if a child process (including
|
||||
// the dispatching process) has focus.
|
||||
eDispatchToParentProcess = 0,
|
||||
// The event must be dispatched in the current process. But of course,
|
||||
// the event may be sent to a child process when it has focus. If there is
|
||||
// no child process, the event may be handled synchronously.
|
||||
eDispatchToCurrentProcess = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* DispatchKeyboardEvent() maybe dispatches aKeyboardEvent.
|
||||
*
|
||||
@ -212,13 +192,11 @@ public:
|
||||
* set nsEventStatus_eIgnore. After dispatching
|
||||
* a event and it's consumed this returns
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aDispatchTo See comments of DispatchTo.
|
||||
* @return true if an event is dispatched. Otherwise, false.
|
||||
*/
|
||||
bool DispatchKeyboardEvent(uint32_t aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo = eDispatchToParentProcess);
|
||||
nsEventStatus& aStatus);
|
||||
|
||||
/**
|
||||
* MaybeDispatchKeypressEvents() maybe dispatches a keypress event which is
|
||||
@ -232,14 +210,11 @@ public:
|
||||
* When this method dispatches one or more keypress
|
||||
* events and one of them is consumed, this returns
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aDispatchTo See comments of DispatchTo.
|
||||
* @return true if one or more events are dispatched.
|
||||
* Otherwise, false.
|
||||
*/
|
||||
bool MaybeDispatchKeypressEvents(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo =
|
||||
eDispatchToParentProcess);
|
||||
nsEventStatus& aStatus);
|
||||
|
||||
private:
|
||||
// mWidget is owner of the instance. When this is created, this is set.
|
||||
@ -298,7 +273,6 @@ private:
|
||||
*/
|
||||
void InitEvent(WidgetGUIEvent& aEvent) const;
|
||||
|
||||
|
||||
/**
|
||||
* DispatchEvent() dispatches aEvent on aWidget.
|
||||
*/
|
||||
@ -306,16 +280,6 @@ private:
|
||||
WidgetGUIEvent& aEvent,
|
||||
nsEventStatus& aStatus);
|
||||
|
||||
/**
|
||||
* DispatchInputEvent() dispatches aEvent on aWidget.
|
||||
*
|
||||
* @param aDispatchTo See comments of DispatchTo.
|
||||
*/
|
||||
nsresult DispatchInputEvent(nsIWidget* aWidget,
|
||||
WidgetInputEvent& aEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo);
|
||||
|
||||
/**
|
||||
* StartCompositionAutomaticallyIfNecessary() starts composition if it hasn't
|
||||
* been started it yet.
|
||||
@ -344,7 +308,6 @@ private:
|
||||
* set nsEventStatus_eIgnore. After dispatching
|
||||
* a event and it's consumed this returns
|
||||
* nsEventStatus_eConsumeNoDefault.
|
||||
* @param aDispatchTo See comments of DispatchTo.
|
||||
* @param aIndexOfKeypress This must be 0 if aMessage isn't NS_KEY_PRESS or
|
||||
* aKeyboard.mKeyNameIndex isn't
|
||||
* KEY_NAME_INDEX_USE_STRING. Otherwise, i.e.,
|
||||
@ -357,8 +320,6 @@ private:
|
||||
bool DispatchKeyboardEventInternal(uint32_t aMessage,
|
||||
const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
nsEventStatus& aStatus,
|
||||
DispatchTo aDispatchTo =
|
||||
eDispatchToParentProcess,
|
||||
uint32_t aIndexOfKeypress = 0);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user