mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 905573 - Add setInputMethodActive to browser elements to allow gaia system set the active IME app. r=fabrice
This commit is contained in:
parent
6322ff8a35
commit
840767de6b
@ -31,7 +31,7 @@ this.Keyboard = {
|
||||
if (this._messageManager && !Cu.isDeadWrapper(this._messageManager))
|
||||
return this._messageManager;
|
||||
|
||||
throw Error('no message manager set');
|
||||
return null;
|
||||
},
|
||||
|
||||
set messageManager(mm) {
|
||||
@ -92,6 +92,10 @@ this.Keyboard = {
|
||||
// If we get a 'Keyboard:XXX' message, check that the sender has the
|
||||
// keyboard permission.
|
||||
if (msg.name.indexOf("Keyboard:") != -1) {
|
||||
if (!this.messageManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mm;
|
||||
try {
|
||||
mm = msg.target.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
|
@ -199,15 +199,51 @@ MozKeyboard.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
const TESTING_ENABLED_PREF = "dom.mozInputMethod.testing";
|
||||
|
||||
/*
|
||||
* A WeakMap to map input method iframe window to its active status.
|
||||
*/
|
||||
let WindowMap = {
|
||||
// WeakMap of <window, boolean> pairs.
|
||||
_map: null,
|
||||
|
||||
/*
|
||||
* Check if the given window is active.
|
||||
*/
|
||||
isActive: function(win) {
|
||||
if (!this._map || !win) {
|
||||
return false;
|
||||
}
|
||||
return this._map.get(win, false);
|
||||
},
|
||||
|
||||
/*
|
||||
* Set the active status of the given window.
|
||||
*/
|
||||
setActive: function(win, isActive) {
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
if (!this._map) {
|
||||
this._map = new WeakMap();
|
||||
}
|
||||
this._map.set(win, isActive);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ==============================================
|
||||
* InputMethodManager
|
||||
* ==============================================
|
||||
*/
|
||||
function MozInputMethodManager() { }
|
||||
function MozInputMethodManager(win) {
|
||||
this._window = win;
|
||||
}
|
||||
|
||||
MozInputMethodManager.prototype = {
|
||||
_supportsSwitching: false,
|
||||
_window: null,
|
||||
|
||||
classID: Components.ID("{7e9d7280-ef86-11e2-b778-0800200c9a66}"),
|
||||
|
||||
@ -224,18 +260,30 @@ MozInputMethodManager.prototype = {
|
||||
}),
|
||||
|
||||
showAll: function() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return;
|
||||
}
|
||||
cpmm.sendAsyncMessage('Keyboard:ShowInputMethodPicker', {});
|
||||
},
|
||||
|
||||
next: function() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return;
|
||||
}
|
||||
cpmm.sendAsyncMessage('Keyboard:SwitchToNextInputMethod', {});
|
||||
},
|
||||
|
||||
supportsSwitching: function() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return false;
|
||||
}
|
||||
return this._supportsSwitching;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return;
|
||||
}
|
||||
cpmm.sendAsyncMessage('Keyboard:RemoveFocus', {});
|
||||
}
|
||||
};
|
||||
@ -250,6 +298,7 @@ function MozInputMethod() { }
|
||||
MozInputMethod.prototype = {
|
||||
_inputcontext: null,
|
||||
_layouts: {},
|
||||
_window: null,
|
||||
|
||||
classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"),
|
||||
|
||||
@ -268,17 +317,26 @@ MozInputMethod.prototype = {
|
||||
}),
|
||||
|
||||
init: function mozInputMethodInit(win) {
|
||||
let principal = win.document.nodePrincipal;
|
||||
let perm = Services.perms
|
||||
.testExactPermissionFromPrincipal(principal, "keyboard");
|
||||
if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
dump("No permission to use the keyboard API for " +
|
||||
principal.origin + "\n");
|
||||
return null;
|
||||
// Check if we're in testing mode.
|
||||
let isTesting = false;
|
||||
try {
|
||||
isTesting = Services.prefs.getBoolPref(TESTING_ENABLED_PREF);
|
||||
} catch (e) {}
|
||||
|
||||
// Don't bypass the permission check if not in testing mode.
|
||||
if (!isTesting) {
|
||||
let principal = win.document.nodePrincipal;
|
||||
let perm = Services.perms
|
||||
.testExactPermissionFromPrincipal(principal, "keyboard");
|
||||
if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
dump("No permission to use the keyboard API for " +
|
||||
principal.origin + "\n");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
this._window = win;
|
||||
this._mgmt = new MozInputMethodManager();
|
||||
this._mgmt = new MozInputMethodManager(win);
|
||||
this.innerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
@ -288,11 +346,6 @@ MozInputMethod.prototype = {
|
||||
cpmm.addMessageListener('Keyboard:SelectionChange', this);
|
||||
cpmm.addMessageListener('Keyboard:GetContext:Result:OK', this);
|
||||
cpmm.addMessageListener('Keyboard:LayoutsChange', this);
|
||||
|
||||
// If there already is an active context, then this will trigger
|
||||
// a GetContext:Result:OK event, and we can initialize ourselves.
|
||||
// Otherwise silently ignored.
|
||||
cpmm.sendAsyncMessage("Keyboard:GetContext", {});
|
||||
},
|
||||
|
||||
uninit: function mozInputMethodUninit() {
|
||||
@ -307,6 +360,10 @@ MozInputMethod.prototype = {
|
||||
},
|
||||
|
||||
receiveMessage: function mozInputMethodReceiveMsg(msg) {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let json = msg.json;
|
||||
|
||||
switch(msg.name) {
|
||||
@ -338,11 +395,18 @@ MozInputMethod.prototype = {
|
||||
},
|
||||
|
||||
get mgmt() {
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._mgmt;
|
||||
},
|
||||
|
||||
get inputcontext() {
|
||||
return this._inputcontext;
|
||||
if (!WindowMap.isActive(this._window)) {
|
||||
return null;
|
||||
}
|
||||
return this._inputcontext;
|
||||
},
|
||||
|
||||
set oninputcontextchange(handler) {
|
||||
@ -372,6 +436,27 @@ MozInputMethod.prototype = {
|
||||
let event = new this._window.Event("inputcontextchange",
|
||||
ObjectWrapper.wrap({}, this._window));
|
||||
this.__DOM_IMPL__.dispatchEvent(event);
|
||||
},
|
||||
|
||||
setActive: function mozInputMethodSetActive(isActive) {
|
||||
if (WindowMap.isActive(this._window) === isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
WindowMap.setActive(this._window, isActive);
|
||||
|
||||
if (isActive) {
|
||||
// Activate current input method.
|
||||
// If there is already an active context, then this will trigger
|
||||
// a GetContext:Result:OK event, and we can initialize ourselves.
|
||||
// Otherwise silently ignored.
|
||||
cpmm.sendAsyncMessage("Keyboard:GetContext", {});
|
||||
} else {
|
||||
// Deactive current input method.
|
||||
if (this._inputcontext) {
|
||||
this.setInputContext(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -400,6 +485,7 @@ function MozInputContext(ctx) {
|
||||
MozInputContext.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
_window: null,
|
||||
_context: null,
|
||||
_contextId: -1,
|
||||
|
||||
@ -452,6 +538,8 @@ MozInputContext.prototype = {
|
||||
this._context[k] = null;
|
||||
}
|
||||
}
|
||||
|
||||
this._window = null;
|
||||
},
|
||||
|
||||
receiveMessage: function ic_receiveMessage(msg) {
|
||||
@ -558,8 +646,7 @@ MozInputContext.prototype = {
|
||||
|
||||
getText: function ic_getText(offset, length) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmm.sendAsyncMessage('Keyboard:GetText', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
@ -587,8 +674,7 @@ MozInputContext.prototype = {
|
||||
|
||||
setSelectionRange: function ic_setSelectionRange(start, length) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmm.sendAsyncMessage("Keyboard:SetSelectionRange", {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
@ -616,8 +702,7 @@ MozInputContext.prototype = {
|
||||
|
||||
replaceSurroundingText: function ic_replaceSurrText(text, offset, length) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmm.sendAsyncMessage('Keyboard:ReplaceSurroundingText', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
@ -634,8 +719,7 @@ MozInputContext.prototype = {
|
||||
|
||||
sendKey: function ic_sendKey(keyCode, charCode, modifiers) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmm.sendAsyncMessage('Keyboard:SendKey', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
@ -648,8 +732,7 @@ MozInputContext.prototype = {
|
||||
|
||||
setComposition: function ic_setComposition(text, cursor, clauses) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmm.sendAsyncMessage('Keyboard:SetComposition', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
@ -662,14 +745,26 @@ MozInputContext.prototype = {
|
||||
|
||||
endComposition: function ic_endComposition(text) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
return this._sendPromise(function(resolverId) {
|
||||
cpmm.sendAsyncMessage('Keyboard:EndComposition', {
|
||||
contextId: self._contextId,
|
||||
requestId: resolverId,
|
||||
text: text || ''
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_sendPromise: function(callback) {
|
||||
let self = this;
|
||||
return this.createPromise(function(resolve, reject) {
|
||||
let resolverId = self.getPromiseResolverId({ resolve: resolve, reject: reject });
|
||||
if (!WindowMap.isActive(self._window)) {
|
||||
self.removePromiseResolver(resolverId);
|
||||
reject('Input method is not active.');
|
||||
return;
|
||||
}
|
||||
callback(resolverId);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -287,6 +287,11 @@ this.PermissionsTable = { geolocation: {
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"inputmethod-manage": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"wappush": {
|
||||
app: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
|
@ -210,6 +210,7 @@ BrowserElementChild.prototype = {
|
||||
"owner-visibility-change": this._recvOwnerVisibilityChange,
|
||||
"exit-fullscreen": this._recvExitFullscreen.bind(this),
|
||||
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
|
||||
"set-input-method-active": this._recvSetInputMethodActive.bind(this),
|
||||
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this)
|
||||
}
|
||||
|
||||
@ -886,6 +887,20 @@ BrowserElementChild.prototype = {
|
||||
webNav.stop(webNav.STOP_NETWORK);
|
||||
},
|
||||
|
||||
_recvSetInputMethodActive: function(data) {
|
||||
let msgData = { id: data.json.id };
|
||||
// Unwrap to access webpage content.
|
||||
let nav = XPCNativeWrapper.unwrap(content.document.defaultView.navigator);
|
||||
if (nav.mozInputMethod) {
|
||||
// Wrap to access the chrome-only attribute setActive.
|
||||
new XPCNativeWrapper(nav.mozInputMethod).setActive(data.json.args.isActive);
|
||||
msgData.successRv = null;
|
||||
} else {
|
||||
msgData.errorMsg = 'Cannot access mozInputMethod.';
|
||||
}
|
||||
sendAsyncMsg('got-set-input-method-active', msgData);
|
||||
},
|
||||
|
||||
_keyEventHandler: function(e) {
|
||||
if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
|
||||
sendAsyncMsg('keyevent', {
|
||||
|
@ -92,6 +92,10 @@ this.BrowserElementParentBuilder = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The active input method iframe.
|
||||
let activeInputFrame = null;
|
||||
|
||||
function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
||||
debug("Creating new BrowserElementParent object for " + frameLoader);
|
||||
this._domRequestCounter = 0;
|
||||
@ -141,6 +145,7 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
||||
"exit-fullscreen": this._exitFullscreen,
|
||||
"got-visible": this._gotDOMRequestResult,
|
||||
"visibilitychange": this._childVisibilityChange,
|
||||
"got-set-input-method-active": this._gotDOMRequestResult
|
||||
}
|
||||
|
||||
this._mm.addMessageListener('browser-element-api:call', function(aMsg) {
|
||||
@ -188,6 +193,13 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
||||
defineDOMRequestMethod('getCanGoBack', 'get-can-go-back');
|
||||
defineDOMRequestMethod('getCanGoForward', 'get-can-go-forward');
|
||||
|
||||
let principal = this._frameElement.ownerDocument.nodePrincipal;
|
||||
let perm = Services.perms
|
||||
.testExactPermissionFromPrincipal(principal, "inputmethod-manage");
|
||||
if (perm === Ci.nsIPermissionManager.ALLOW_ACTION) {
|
||||
defineMethod('setInputMethodActive', this._setInputMethodActive);
|
||||
}
|
||||
|
||||
// Listen to visibilitychange on the iframe's owner window, and forward
|
||||
// changes down to the child. We want to do this while registering as few
|
||||
// visibilitychange listeners on _window as possible, because such a listener
|
||||
@ -581,6 +593,47 @@ BrowserElementParent.prototype = {
|
||||
this._sendAsyncMsg('deactivate-next-paint-listener');
|
||||
},
|
||||
|
||||
_setInputMethodActive: function(isActive) {
|
||||
if (typeof isActive !== 'boolean') {
|
||||
throw Components.Exception("Invalid argument",
|
||||
Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
let req = Services.DOMRequest.createRequest(this._window);
|
||||
|
||||
// Deactivate the old input method if needed.
|
||||
if (activeInputFrame && isActive) {
|
||||
let reqOld = XPCNativeWrapper.unwrap(activeInputFrame)
|
||||
.setInputMethodActive(false);
|
||||
reqOld.onsuccess = function() {
|
||||
activeInputFrame = null;
|
||||
this._sendSetInputMethodActiveDOMRequest(req, isActive);
|
||||
}.bind(this);
|
||||
reqOld.onerror = function() {
|
||||
Services.DOMRequest.fireErrorAsync(req,
|
||||
'Failed to deactivate the old input method: ' +
|
||||
reqOld.error + '.');
|
||||
};
|
||||
} else {
|
||||
this._sendSetInputMethodActiveDOMRequest(req, isActive);
|
||||
}
|
||||
return req;
|
||||
},
|
||||
|
||||
_sendSetInputMethodActiveDOMRequest: function(req, isActive) {
|
||||
let id = 'req_' + this._domRequestCounter++;
|
||||
let data = {
|
||||
id : id,
|
||||
args: { isActive: isActive }
|
||||
};
|
||||
if (this._sendAsyncMsg('set-input-method-active', data)) {
|
||||
activeInputFrame = this._frameElement;
|
||||
this._pendingDOMRequests[id] = req;
|
||||
} else {
|
||||
Services.DOMRequest.fireErrorAsync(req, 'fail');
|
||||
}
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(data) {
|
||||
let evt = this._window.document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent(data.json.type, true, true, this._window,
|
||||
|
@ -163,6 +163,11 @@ MOCHITEST_FILES = \
|
||||
test_browserElement_inproc_BrowserWindowResize.html \
|
||||
$(NULL)
|
||||
|
||||
# Disabled until we fix bug 906096.
|
||||
# browserElement_SetInputMethodActive.js \
|
||||
# test_browserElement_inproc_SetInputMethodActive.html \
|
||||
# file_inputmethod.html \
|
||||
|
||||
# Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=774100
|
||||
# test_browserElement_inproc_Reload.html \
|
||||
|
||||
@ -239,4 +244,7 @@ MOCHITEST_FILES += \
|
||||
test_browserElement_oop_BrowserWindowResize.html \
|
||||
$(NULL)
|
||||
|
||||
# Disabled until we fix bug 906096.
|
||||
# test_browserElement_oop_SetInputMethodActive.html \
|
||||
|
||||
endif #}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Bug 905573 - Add setInputMethodActive to browser elements to allow gaia
|
||||
// system set the active IME app.
|
||||
'use strict';
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
function setup() {
|
||||
SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", true);
|
||||
SpecialPowers.setBoolPref("dom.mozInputMethod.testing", true);
|
||||
SpecialPowers.addPermission('inputmethod-manage', true, document);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
SpecialPowers.setBoolPref("dom.mozInputMethod.enabled", false);
|
||||
SpecialPowers.setBoolPref("dom.mozInputMethod.testing", false);
|
||||
SpecialPowers.removePermission("inputmethod-manage", document);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Create an input field to receive string from input method iframes.
|
||||
let input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
document.body.appendChild(input);
|
||||
|
||||
// Create two input method iframes.
|
||||
let frames = [];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
frames[i] = document.createElement('iframe');
|
||||
SpecialPowers.wrap(frames[i]).mozbrowser = true;
|
||||
// When the input method iframe is activated, it will send the URL
|
||||
// hash to current focused element. We set different hash to each
|
||||
// iframe so that iframes can be differentiated by their hash.
|
||||
frames[i].src = 'file_inputmethod.html#' + i;
|
||||
frames[i].setAttribute('mozapp', location.href.replace(/[^/]+$/, 'file_inputmethod.webapp'));
|
||||
document.body.appendChild(frames[i]);
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
|
||||
// Set focus to the input field and wait for input methods' inputting.
|
||||
SpecialPowers.DOMWindowUtils.focus(input);
|
||||
var timerId = null;
|
||||
input.oninput = function() {
|
||||
// The texts sent from the first and the second input method are '#0' and
|
||||
// '#1' respectively.
|
||||
switch (count) {
|
||||
case 1:
|
||||
is(input.value, '#0', 'Failed to get correct input from the first iframe.');
|
||||
testNextInputMethod();
|
||||
break;
|
||||
case 2:
|
||||
is(input.value, '#0#1', 'Failed to get correct input from the second iframe.');
|
||||
// Do nothing and wait for the next input from the second iframe.
|
||||
count++;
|
||||
break;
|
||||
case 3:
|
||||
is(input.value, '#0#1#1', 'Failed to get correct input from the second iframe.');
|
||||
// Receive the second input from the second iframe.
|
||||
count++;
|
||||
// Deactive the second iframe.
|
||||
frames[1].setInputMethodActive(false);
|
||||
// Wait for a short while to ensure the second iframe is not active any
|
||||
// more.
|
||||
timerId = setTimeout(function() {
|
||||
ok(true, 'Successfully deactivate the second iframe.');
|
||||
tearDown();
|
||||
}, 1000);
|
||||
break;
|
||||
default:
|
||||
ok(false, 'Failed to deactivate the second iframe.');
|
||||
clearTimeout(timerId);
|
||||
tearDown();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ok(frames[0].setInputMethodActive, 'Cannot access setInputMethodActive.');
|
||||
|
||||
function testNextInputMethod() {
|
||||
frames[count++].setInputMethodActive(true);
|
||||
}
|
||||
|
||||
// Wait for a short while to let input method get ready.
|
||||
setTimeout(function() {
|
||||
testNextInputMethod();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
setup();
|
||||
addEventListener('testready', runTest);
|
21
dom/browser-element/mochitest/file_inputmethod.html
Normal file
21
dom/browser-element/mochitest/file_inputmethod.html
Normal file
@ -0,0 +1,21 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var im = navigator.mozInputMethod;
|
||||
if (im) {
|
||||
var intervalId = null;
|
||||
// Automatically append location hash to current input field.
|
||||
im.oninputcontextchange = function() {
|
||||
var ctx = im.inputcontext;
|
||||
if (ctx) {
|
||||
intervalId = setInterval(function() {
|
||||
ctx.replaceSurroundingText(location.hash);
|
||||
}, 500);
|
||||
} else {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 905573</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_SetInputMethodActive.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 905573</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_SetInputMethodActive.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -23,6 +23,10 @@ interface MozInputMethod : EventTarget {
|
||||
// allow to mutate. this attribute should be null when there is no
|
||||
// text field currently focused.
|
||||
readonly attribute MozInputContext? inputcontext;
|
||||
|
||||
[ChromeOnly]
|
||||
// Activate or decactive current input method window.
|
||||
void setActive(boolean isActive);
|
||||
};
|
||||
|
||||
// Manages the list of IMEs, enables/disables IME and switches to an
|
||||
|
Loading…
Reference in New Issue
Block a user