Bug 582893 IME isn't disabled when password fields on sheet dialog get focus r=smichaud, b2.0=final+

This commit is contained in:
Masayuki Nakano 2010-08-16 17:20:27 +09:00
parent be04bb141a
commit 30970d30d2
3 changed files with 108 additions and 18 deletions

View File

@ -259,6 +259,10 @@ public:
static CFArrayRef CreateAllIMEModeList();
static void DebugPrintAllIMEModes(PRLogModuleInfo* aLogModuleInfo);
// Don't use ::TSMGetActiveDocument() API directly, the document may not
// be what you want.
static TSMDocumentID GetCurrentTSMDocumentID();
protected:
// The owner of this instance. The result of mOwnerWidget->TextInputHandler
// returns this instance. This must not be null after initialized.

View File

@ -682,6 +682,17 @@ nsCocoaIMEHandler::DebugPrintAllIMEModes(PRLogModuleInfo* aLogModuleInfo)
::CFRelease(list);
}
//static
TSMDocumentID
nsCocoaIMEHandler::GetCurrentTSMDocumentID()
{
// On OS X 10.6.x at least, ::TSMGetActiveDocument() has a bug that prevents
// it from returning accurate results unless
// [NSInputManager currentInputManager] is called first.
// So, we need to call [NSInputManager currentInputManager] first here.
[NSInputManager currentInputManager];
return ::TSMGetActiveDocument();
}
#pragma mark -
@ -706,8 +717,8 @@ nsCocoaIMEHandler::ResetIMEWindowLevel()
#ifdef DEBUG_IME_HANDLER
DebugPrintPointer(this);
NSLog(@"nsCocoaIMEHandler::ResetIMEWindowLevel");
NSLog(@" IsFocused:%s ::TSMGetActiveDocument():%p",
TrueOrFalse(IsFocused()), ::TSMGetActiveDocument());
NSLog(@" IsFocused:%s GetCurrentTSMDocumentID():%p",
TrueOrFalse(IsFocused()), GetCurrentTSMDocumentID());
#endif // DEBUG_IME_HANDLER
if (!mView)
@ -719,7 +730,7 @@ nsCocoaIMEHandler::ResetIMEWindowLevel()
return;
}
TSMDocumentID doc = ::TSMGetActiveDocument();
TSMDocumentID doc = GetCurrentTSMDocumentID();
if (!doc) {
// retry
mPendingMethods |= kResetIMEWindowLevel;
@ -752,7 +763,7 @@ nsCocoaIMEHandler::ResetIMEWindowLevel()
if (windowLevel == NSNormalWindowLevel)
windowLevel++;
::TSMSetDocumentProperty(::TSMGetActiveDocument(),
::TSMSetDocumentProperty(GetCurrentTSMDocumentID(),
kTSMDocumentWindowLevelPropertyTag,
sizeof(windowLevel), &windowLevel);
@ -803,8 +814,8 @@ nsCocoaIMEHandler::SyncASCIICapableOnly()
#ifdef DEBUG_IME_HANDLER
DebugPrintPointer(this);
NSLog(@"nsCocoaIMEHandler::SyncASCIICapableOnly");
NSLog(@" IsFocused:%s ::TSMGetActiveDocument():%p",
TrueOrFalse(IsFocused()), ::TSMGetActiveDocument());
NSLog(@" IsFocused:%s GetCurrentTSMDocumentID():%p",
TrueOrFalse(IsFocused()), GetCurrentTSMDocumentID());
#endif
if (!mView)
@ -816,7 +827,7 @@ nsCocoaIMEHandler::SyncASCIICapableOnly()
return;
}
TSMDocumentID doc = ::TSMGetActiveDocument();
TSMDocumentID doc = GetCurrentTSMDocumentID();
if (!doc) {
// retry
mPendingMethods |= kSyncASCIICapableOnly;
@ -847,12 +858,9 @@ nsCocoaIMEHandler::ResetTimer()
"There are not pending methods, why this is called?");
if (mTimer) {
mTimer->Cancel();
return;
}
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
if (!mTimer) {
NS_ERROR("mTimer is null");
return;
} else {
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_TRUE(mTimer, );
}
mTimer->InitWithFuncCallback(FlushPendingMethods, this, 0,
nsITimer::TYPE_ONE_SHOT);
@ -863,6 +871,11 @@ nsCocoaIMEHandler::ExecutePendingMethods()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (mTimer) {
mTimer->Cancel();
mTimer = nsnull;
}
if (![[NSApplication sharedApplication] isActive]) {
mIsInFocusProcessing = PR_FALSE;
// If we're not active, we should retry at focus event
@ -873,10 +886,6 @@ nsCocoaIMEHandler::ExecutePendingMethods()
// First, reset the pending method flags because if each methods cannot
// run now, they can reentry to the pending flags by theirselves.
mPendingMethods = 0;
if (mTimer) {
mTimer->Cancel();
mTimer = nsnull;
}
if (pendingMethods & kDiscardIMEComposition)
DiscardIMEComposition();
@ -1164,7 +1173,8 @@ nsCocoaIMEHandler::IsFocused()
NS_ENSURE_TRUE(mView, PR_FALSE);
NSWindow* window = [mView window];
NS_ENSURE_TRUE(window, PR_FALSE);
return [window firstResponder] == mView && [window isMainWindow] &&
return [window firstResponder] == mView &&
([window isMainWindow] || [window isSheet]) &&
[[NSApplication sharedApplication] isActive];
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(PR_FALSE);

View File

@ -861,6 +861,79 @@ function runEditableSubframeTests()
"width=600,height=600");
}
function runTestPasswordFieldOnDialog()
{
if (!kIMEEnabledSupported) {
return;
}
if (document.activeElement) {
document.activeElement.blur();
}
var dialog;
function WindowObserver()
{
Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService).
addObserver(this, "domwindowopened", false);
}
WindowObserver.prototype = {
QueryInterface: function (iid)
{
if (iid.equals(Components.interfaces.nsIObserver) ||
iid.equals(Components.interfaces.nsISupports)) {
return this;
}
},
observe: function (subject, topic, data)
{
if (topic === "domwindowopened") {
ok(true, "dialog window is created");
dialog = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
dialog.addEventListener("load", onPasswordDialogLoad, false);
}
}
};
var observer = new WindowObserver();
var arg1 = new Object(), arg2 = new Object();
Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService).
promptPassword(window, "title", "text", arg1, "msg", arg2);
ok(true, "password dialog was closed");
Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService).
removeObserver(observer, "domwindowopened");
var passwordField;
function onPasswordDialogLoad()
{
ok(true, "onPasswordDialogLoad is called");
dialog.removeEventListener("load", onPasswordDialogLoad, false);
passwordField = dialog.document.getElementById("password1Textbox");
passwordField.addEventListener("focus", onPasswordFieldFocus, false);
}
function onPasswordFieldFocus()
{
ok(true, "onPasswordFieldFocus is called");
passwordField.removeEventListener("focus", onPasswordFieldFocus, false);
var utils = dialog.
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
is(utils.IMEStatus, utils.IME_STATUS_PASSWORD,
"IME isn't disabled on a password field of password dialog");
synthesizeKey("VK_ESCAPE", { }, dialog);
}
}
function runTests()
{
if (!kIMEEnabledSupported && !kIMEOpenSupported)
@ -908,6 +981,9 @@ function runTests()
// test whether the IME state and composition are not changed unexpectedly
runEditorFlagChangeTests();
// test password field on dialog
runTestPasswordFieldOnDialog();
runASyncTests();
}