diff --git a/accessible/src/atk/nsApplicationAccessibleWrap.cpp b/accessible/src/atk/nsApplicationAccessibleWrap.cpp index c8ee40cf0e0..d08280d8890 100644 --- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp +++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp @@ -44,7 +44,8 @@ #include "nsMai.h" #include "prlink.h" #include "prenv.h" -#include "nsIPrefBranch.h" +#include "mozilla/Preferences.h" +#include "nsIGConfService.h" #include "nsIServiceManager.h" #include "nsAutoPtr.h" #include "nsAccessibilityService.h" @@ -53,6 +54,8 @@ #include #include +using namespace mozilla; + typedef GType (* AtkGetTypeType) (void); GType g_atk_hyperlink_impl_type = G_TYPE_INVALID; static bool sATKChecked = false; @@ -61,10 +64,12 @@ static const char sATKLibName[] = "libatk-1.0.so.0"; static const char sATKHyperlinkImplGetTypeSymbol[] = "atk_hyperlink_impl_get_type"; static const char sAccEnv [] = "GNOME_ACCESSIBILITY"; -static const char sSysPrefService [] = - "@mozilla.org/system-preference-service;1"; +static const char sUseSystemPrefsKey[] = + "config.use_system_prefs"; static const char sAccessibilityKey [] = "config.use_system_prefs.accessibility"; +static const char sGconfAccessibilityKey[] = + "/desktop/gnome/interface/accessibility"; /* gail function pointer */ static guint (* gail_add_global_event_listener) (GSignalEmissionHook listener, @@ -625,11 +630,17 @@ nsApplicationAccessibleWrap::Init() isGnomeATEnabled = !!atoi(envValue); } else { //check gconf-2 setting - nsresult rv; - nsCOMPtr sysPrefService = - do_GetService(sSysPrefService, &rv); - if (NS_SUCCEEDED(rv) && sysPrefService) { - sysPrefService->GetBoolPref(sAccessibilityKey, &isGnomeATEnabled); + if (Preferences::GetBool(sUseSystemPrefsKey, false)) { + nsresult rv; + nsCOMPtr gconf = + do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && gconf) { + gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey), + &isGnomeATEnabled); + } + } else { + isGnomeATEnabled = + Preferences::GetBool(sAccessibilityKey, false); } } diff --git a/browser/themes/pinstripe/browser.css b/browser/themes/pinstripe/browser.css index 2a96556acd4..07b6e88a09d 100644 --- a/browser/themes/pinstripe/browser.css +++ b/browser/themes/pinstripe/browser.css @@ -88,6 +88,17 @@ padding: 2px 4px; } +/* Because of -moz-box-align: center above, separators will be invisible unless + we set their min-height. See bug 583510 for more information. */ +toolbarseparator { + min-height: 22px; +} + +/* We need more height when toolbar buttons show both icon and text. */ +toolbar[mode="full"] toolbarseparator { + min-height: 36px; +} + #nav-bar { padding-bottom: 4px !important; } diff --git a/browser/themes/pinstripe/places/places.css b/browser/themes/pinstripe/places/places.css index 45db28877a6..038f55c682f 100644 --- a/browser/themes/pinstripe/places/places.css +++ b/browser/themes/pinstripe/places/places.css @@ -2,12 +2,6 @@ /* Sidebars */ -.sidebar-placesTree { - background-color: transparent !important; - -moz-appearance: none !important; - border: none !important; -} - #bookmarksPanel, #history-panel, #sidebar-search-container { diff --git a/build/autoconf/mozheader.m4 b/build/autoconf/mozheader.m4 index a1c2a3c740e..50b3189944c 100644 --- a/build/autoconf/mozheader.m4 +++ b/build/autoconf/mozheader.m4 @@ -36,13 +36,14 @@ dnl the terms of any one of the MPL, the GPL or the LGPL. dnl dnl ***** END LICENSE BLOCK ***** -dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]]) AC_DEFUN([MOZ_CHECK_HEADER], [ dnl Do the transliteration at runtime so arg 1 can be a shell variable. ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(ac_cv_header_$ac_safe, - [ AC_TRY_COMPILE([#include <$1>], , + [ AC_TRY_COMPILE([$4 +#include <$1>], , eval "ac_cv_header_$ac_safe=yes", eval "ac_cv_header_$ac_safe=no") ]) if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then @@ -54,12 +55,12 @@ AC_DEFUN([MOZ_CHECK_HEADER], fi ]) -dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]]) AC_DEFUN([MOZ_CHECK_HEADERS], [ for ac_hdr in $1 do MOZ_CHECK_HEADER($ac_hdr, [ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3) + AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3, [$4]) done ]) diff --git a/configure.in b/configure.in index f6ccc564eaa..3c6c7a81b1d 100644 --- a/configure.in +++ b/configure.in @@ -5935,12 +5935,11 @@ if test "$MOZ_XTF"; then fi dnl ======================================================== -dnl Pref extensions (autoconfig and system-pref) +dnl Pref extensions (autoconfig) dnl ======================================================== MOZ_ARG_DISABLE_BOOL(pref-extensions, [ --disable-pref-extensions - Disable pref extensions such as autoconfig and - system-pref], + Disable pref extensions such as autoconfig], MOZ_PREF_EXTENSIONS=, MOZ_PREF_EXTENSIONS=1 ) @@ -8761,8 +8760,8 @@ if test "$USE_FC_FREETYPE"; then if test "$COMPILE_ENVIRONMENT"; then _SAVE_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS" - AC_CHECK_HEADERS(fontconfig/fcfreetype.h, , - [AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)]) + MOZ_CHECK_HEADERS([fontconfig/fcfreetype.h], , + [AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)], [#include ]) CPPFLAGS="$_SAVE_CPPFLAGS" else AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 8726e49d8ff..b403933a4e7 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1290,11 +1290,6 @@ public: static void TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback, void *aClosure); - /** - * Convert nsIContent::IME_STATUS_* to nsIWidget::IME_STATUS_* - */ - static PRUint32 GetWidgetStatusFromIMEStatus(PRUint32 aState); - /* * Notify when the first XUL menu is opened and when the all XUL menus are * closed. At opening, aInstalling should be TRUE, otherwise, it should be diff --git a/content/base/public/nsIContent.h b/content/base/public/nsIContent.h index cc20a0c3d4b..6afbbe7e1a0 100644 --- a/content/base/public/nsIContent.h +++ b/content/base/public/nsIContent.h @@ -63,8 +63,11 @@ class nsIDOMCSSStyleDeclaration; namespace mozilla { namespace css { class StyleRule; -} -} +} // namespace css +namespace widget { +struct IMEState; +} // namespace widget +} // namespace mozilla enum nsLinkState { eLinkState_Unknown = 0, @@ -75,8 +78,8 @@ enum nsLinkState { // IID for the nsIContent interface #define NS_ICONTENT_IID \ -{ 0x3128b3a0, 0xb609, 0x44e3, \ - { 0xad, 0x91, 0xdc, 0xf1, 0x4a, 0x3f, 0xf6, 0xa0 } } +{ 0xed40a3e5, 0xd7ed, 0x473e, \ + { 0x85, 0xe3, 0x82, 0xc3, 0xf0, 0x41, 0xdb, 0x52 } } /** * A node of content in a document's content model. This interface @@ -84,6 +87,8 @@ enum nsLinkState { */ class nsIContent : public nsINode { public: + typedef mozilla::widget::IMEState IMEState; + #ifdef MOZILLA_INTERNAL_API // If you're using the external API, the only thing you can know about // nsIContent is that it exists with an IID @@ -604,40 +609,18 @@ public: * Get desired IME state for the content. * * @return The desired IME status for the content. - * This is a combination of IME_STATUS_* flags, - * controlling what happens to IME when the content takes focus. - * If this is IME_STATUS_NONE, IME remains in its current state. - * IME_STATUS_ENABLE and IME_STATUS_DISABLE must not be set - * together; likewise IME_STATUS_OPEN and IME_STATUS_CLOSE must - * not be set together. - * If you return IME_STATUS_DISABLE, you should not set the - * OPEN or CLOSE flag; that way, when IME is next enabled, - * the previous OPEN/CLOSE state will be restored (unless the newly - * focused content specifies the OPEN/CLOSE state by setting the OPEN - * or CLOSE flag with the ENABLE flag). - * IME_STATUS_PASSWORD should be returned only from password editor, - * this value has a special meaning. It is used as alternative of - * IME_STATUS_DISABLED. - * IME_STATUS_PLUGIN should be returned only when plug-in has focus. - * When a plug-in is focused content, we should send native events - * directly. Because we don't process some native events, but they may - * be needed by the plug-in. + * This is a combination of an IME enabled value and + * an IME open value of widget::IMEState. + * If you return DISABLED, you should not set the OPEN and CLOSE + * value. + * PASSWORD should be returned only from password editor, this value + * has a special meaning. It is used as alternative of DISABLED. + * PLUGIN should be returned only when plug-in has focus. When a + * plug-in is focused content, we should send native events directly. + * Because we don't process some native events, but they may be needed + * by the plug-in. */ - enum { - IME_STATUS_NONE = 0x0000, - IME_STATUS_ENABLE = 0x0001, - IME_STATUS_DISABLE = 0x0002, - IME_STATUS_PASSWORD = 0x0004, - IME_STATUS_PLUGIN = 0x0008, - IME_STATUS_OPEN = 0x0010, - IME_STATUS_CLOSE = 0x0020 - }; - enum { - IME_STATUS_MASK_ENABLED = IME_STATUS_ENABLE | IME_STATUS_DISABLE | - IME_STATUS_PASSWORD | IME_STATUS_PLUGIN, - IME_STATUS_MASK_OPENED = IME_STATUS_OPEN | IME_STATUS_CLOSE - }; - virtual PRUint32 GetDesiredIMEState(); + virtual IMEState GetDesiredIMEState(); /** * Gets content node with the binding (or native code, possibly on the diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index f26ea0ca083..2285ab4c84a 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -212,6 +212,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); using namespace mozilla::dom; using namespace mozilla::layers; +using namespace mozilla::widget; using namespace mozilla; const char kLoadAsData[] = "loadAsData"; @@ -4026,25 +4027,6 @@ nsContentUtils::DropJSObjects(void* aScriptObjectHolder) return rv; } -/* static */ -PRUint32 -nsContentUtils::GetWidgetStatusFromIMEStatus(PRUint32 aState) -{ - switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) { - case nsIContent::IME_STATUS_DISABLE: - return nsIWidget::IME_STATUS_DISABLED; - case nsIContent::IME_STATUS_ENABLE: - return nsIWidget::IME_STATUS_ENABLED; - case nsIContent::IME_STATUS_PASSWORD: - return nsIWidget::IME_STATUS_PASSWORD; - case nsIContent::IME_STATUS_PLUGIN: - return nsIWidget::IME_STATUS_PLUGIN; - default: - NS_ERROR("The given state doesn't have valid enable state"); - return nsIWidget::IME_STATUS_ENABLED; - } -} - /* static */ void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index a3c136928cb..f7b107e4bfe 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -109,6 +109,7 @@ #include "nsIDOMEventListener.h" #include "nsIWebNavigation.h" #include "nsIBaseWindow.h" +#include "nsIWidget.h" #include "jsapi.h" @@ -1363,11 +1364,11 @@ nsIContent::GetFlattenedTreeParent() const return parent; } -PRUint32 +nsIContent::IMEState nsIContent::GetDesiredIMEState() { if (!IsEditableInternal()) { - return IME_STATUS_DISABLE; + return IMEState(IMEState::DISABLED); } // NOTE: The content for independent editors (e.g., input[type=text], // textarea) must override this method, so, we don't need to worry about @@ -1380,26 +1381,23 @@ nsIContent::GetDesiredIMEState() } nsIDocument* doc = GetCurrentDoc(); if (!doc) { - return IME_STATUS_DISABLE; + return IMEState(IMEState::DISABLED); } nsIPresShell* ps = doc->GetShell(); if (!ps) { - return IME_STATUS_DISABLE; + return IMEState(IMEState::DISABLED); } nsPresContext* pc = ps->GetPresContext(); if (!pc) { - return IME_STATUS_DISABLE; + return IMEState(IMEState::DISABLED); } nsIEditor* editor = GetHTMLEditor(pc); nsCOMPtr imeEditor = do_QueryInterface(editor); if (!imeEditor) { - return IME_STATUS_DISABLE; + return IMEState(IMEState::DISABLED); } - // Use "enable" for the default value because IME is disabled unexpectedly, - // it makes serious a11y problem. - PRUint32 state = IME_STATUS_ENABLE; - nsresult rv = imeEditor->GetPreferredIMEState(&state); - NS_ENSURE_SUCCESS(rv, IME_STATUS_ENABLE); + IMEState state; + imeEditor->GetPreferredIMEState(&state); return state; } diff --git a/content/events/src/nsIMEStateManager.cpp b/content/events/src/nsIMEStateManager.cpp index 573225a9872..901e89844ef 100644 --- a/content/events/src/nsIMEStateManager.cpp +++ b/content/events/src/nsIMEStateManager.cpp @@ -40,7 +40,6 @@ #include "nsIMEStateManager.h" #include "nsCOMPtr.h" -#include "nsIWidget.h" #include "nsIViewManager.h" #include "nsIPresShell.h" #include "nsISupports.h" @@ -51,6 +50,8 @@ #include "nsIDocument.h" #include "nsPresContext.h" #include "nsIDOMWindow.h" +#include "nsIDOMMouseEvent.h" +#include "nsIDOMNSEvent.h" #include "nsContentUtils.h" #include "nsINode.h" #include "nsIFrame.h" @@ -68,6 +69,8 @@ #include "nsIForm.h" #include "nsHTMLFormElement.h" +using namespace mozilla::widget; + /******************************************************************/ /* nsIMEStateManager */ /******************************************************************/ @@ -87,8 +90,10 @@ nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext) return NS_OK; nsCOMPtr widget = GetWidget(sPresContext); if (widget) { - PRUint32 newState = GetNewIMEState(sPresContext, nsnull); - SetIMEState(newState, nsnull, widget, IMEContext::FOCUS_REMOVED); + IMEState newState = GetNewIMEState(sPresContext, nsnull); + InputContextAction action(InputContextAction::CAUSE_UNKNOWN, + InputContextAction::LOST_FOCUS); + SetIMEState(newState, nsnull, widget, action); } sContent = nsnull; sPresContext = nsnull; @@ -112,8 +117,10 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext, nsresult rv = widget->CancelIMEComposition(); if (NS_FAILED(rv)) widget->ResetInputState(); - PRUint32 newState = GetNewIMEState(sPresContext, nsnull); - SetIMEState(newState, nsnull, widget, IMEContext::FOCUS_REMOVED); + IMEState newState = GetNewIMEState(sPresContext, nsnull); + InputContextAction action(InputContextAction::CAUSE_UNKNOWN, + InputContextAction::LOST_FOCUS); + SetIMEState(newState, nsnull, widget, action); } sContent = nsnull; @@ -125,7 +132,16 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext, nsresult nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext, nsIContent* aContent, - PRUint32 aReason) + InputContextAction::Cause aCause) +{ + InputContextAction action(aCause); + return OnChangeFocusInternal(aPresContext, aContent, action); +} + +nsresult +nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext, + nsIContent* aContent, + InputContextAction aAction) { NS_ENSURE_ARG_POINTER(aPresContext); @@ -157,25 +173,22 @@ nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext, } } - PRUint32 newState = GetNewIMEState(aPresContext, aContent); + IMEState newState = GetNewIMEState(aPresContext, aContent); if (aPresContext == sPresContext && aContent == sContent) { // actual focus isn't changing, but if IME enabled state is changing, // we should do it. - PRUint32 newEnabledState = newState & nsIContent::IME_STATUS_MASK_ENABLED; - if (newEnabledState == 0) { - // the enabled state isn't changing, we should do nothing. - return NS_OK; - } - IMEContext context; - if (!widget || NS_FAILED(widget->GetInputMode(context))) { - // this platform doesn't support IME controlling - return NS_OK; - } - if (context.mStatus == - nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) { + InputContext context = widget->GetInputContext(); + if (context.mIMEState.mEnabled == newState.mEnabled) { // the enabled state isn't changing. return NS_OK; } + aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED; + } else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) { + // If aContent isn't null or aContent is null but editable, somebody gets + // focus. + bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED); + aAction.mFocusChange = + gotFocus ? InputContextAction::GOT_FOCUS : InputContextAction::LOST_FOCUS; } // Current IME transaction should commit @@ -189,10 +202,8 @@ nsIMEStateManager::OnChangeFocus(nsPresContext* aPresContext, oldWidget->ResetInputState(); } - if (newState != nsIContent::IME_STATUS_NONE) { - // Update IME state for new focus widget - SetIMEState(newState, aContent, widget, aReason); - } + // Update IME state for new focus widget + SetIMEState(newState, aContent, widget, aAction); sPresContext = aPresContext; sContent = aContent; @@ -205,19 +216,60 @@ nsIMEStateManager::OnInstalledMenuKeyboardListener(bool aInstalling) { sInstalledMenuKeyboardListener = aInstalling; - PRUint32 reason = aInstalling ? IMEContext::FOCUS_MOVED_TO_MENU - : IMEContext::FOCUS_MOVED_FROM_MENU; - OnChangeFocus(sPresContext, sContent, reason); + InputContextAction action(InputContextAction::CAUSE_UNKNOWN, + aInstalling ? InputContextAction::MENU_GOT_PSEUDO_FOCUS : + InputContextAction::MENU_LOST_PSEUDO_FOCUS); + OnChangeFocusInternal(sPresContext, sContent, action); } void -nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent) +nsIMEStateManager::OnClickInEditor(nsPresContext* aPresContext, + nsIContent* aContent, + nsIDOMMouseEvent* aMouseEvent) +{ + if (sPresContext != aPresContext || sContent != aContent) { + return; + } + + nsCOMPtr widget = GetWidget(aPresContext); + NS_ENSURE_TRUE(widget, ); + + bool isTrusted; + nsCOMPtr NSEvent = do_QueryInterface(aMouseEvent); + nsresult rv = NSEvent->GetIsTrusted(&isTrusted); + NS_ENSURE_SUCCESS(rv, ); + if (!isTrusted) { + return; // ignore untrusted event. + } + + PRUint16 button; + rv = aMouseEvent->GetButton(&button); + NS_ENSURE_SUCCESS(rv, ); + if (button != 0) { + return; // not a left click event. + } + + PRInt32 clickCount; + rv = aMouseEvent->GetDetail(&clickCount); + NS_ENSURE_SUCCESS(rv, ); + if (clickCount != 1) { + return; // should notify only first click event. + } + + InputContextAction action(InputContextAction::CAUSE_MOUSE, + InputContextAction::FOCUS_NOT_CHANGED); + IMEState newState = GetNewIMEState(aPresContext, aContent); + SetIMEState(newState, aContent, widget, action); +} + +void +nsIMEStateManager::UpdateIMEState(const IMEState &aNewIMEState, + nsIContent* aContent) { if (!sPresContext) { NS_WARNING("ISM doesn't know which editor has focus"); return; } - NS_PRECONDITION(aNewIMEState != 0, "aNewIMEState doesn't specify new state."); nsCOMPtr widget = GetWidget(sPresContext); if (!widget) { NS_WARNING("focused widget is not found"); @@ -225,43 +277,41 @@ nsIMEStateManager::UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent) } // Don't update IME state when enabled state isn't actually changed. - IMEContext context; - nsresult rv = widget->GetInputMode(context); - if (NS_FAILED(rv)) { - return; // This platform doesn't support controling the IME state. - } - PRUint32 newEnabledState = aNewIMEState & nsIContent::IME_STATUS_MASK_ENABLED; - if (context.mStatus == - nsContentUtils::GetWidgetStatusFromIMEStatus(newEnabledState)) { + InputContext context = widget->GetInputContext(); + if (context.mIMEState.mEnabled == aNewIMEState.mEnabled) { return; } // commit current composition widget->ResetInputState(); - SetIMEState(aNewIMEState, aContent, widget, IMEContext::EDITOR_STATE_MODIFIED); + InputContextAction action(InputContextAction::CAUSE_UNKNOWN, + InputContextAction::FOCUS_NOT_CHANGED); + SetIMEState(aNewIMEState, aContent, widget, action); } -PRUint32 +IMEState nsIMEStateManager::GetNewIMEState(nsPresContext* aPresContext, nsIContent* aContent) { // On Printing or Print Preview, we don't need IME. if (aPresContext->Type() == nsPresContext::eContext_PrintPreview || aPresContext->Type() == nsPresContext::eContext_Print) { - return nsIContent::IME_STATUS_DISABLE; + return IMEState(IMEState::DISABLED); } - if (sInstalledMenuKeyboardListener) - return nsIContent::IME_STATUS_DISABLE; + if (sInstalledMenuKeyboardListener) { + return IMEState(IMEState::DISABLED); + } if (!aContent) { // Even if there are no focused content, the focused document might be // editable, such case is design mode. nsIDocument* doc = aPresContext->Document(); - if (doc && doc->HasFlag(NODE_IS_EDITABLE)) - return nsIContent::IME_STATUS_ENABLE; - return nsIContent::IME_STATUS_DISABLE; + if (doc && doc->HasFlag(NODE_IS_EDITABLE)) { + return IMEState(IMEState::ENABLED); + } + return IMEState(IMEState::DISABLED); } return aContent->GetDesiredIMEState(); @@ -290,65 +340,62 @@ private: }; void -nsIMEStateManager::SetIMEState(PRUint32 aState, +nsIMEStateManager::SetIMEState(const IMEState &aState, nsIContent* aContent, nsIWidget* aWidget, - PRUint32 aReason) + InputContextAction aAction) { - if (aState & nsIContent::IME_STATUS_MASK_ENABLED) { - if (!aWidget) - return; + NS_ENSURE_TRUE(aWidget, ); - PRUint32 state = nsContentUtils::GetWidgetStatusFromIMEStatus(aState); - IMEContext context; - context.mStatus = state; - - if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML && - (aContent->Tag() == nsGkAtoms::input || - aContent->Tag() == nsGkAtoms::textarea)) { - aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, - context.mHTMLInputType); - aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint, - context.mActionHint); + InputContext oldContext = aWidget->GetInputContext(); - // if we don't have an action hint and return won't submit the form use "next" - if (context.mActionHint.IsEmpty() && aContent->Tag() == nsGkAtoms::input) { - bool willSubmit = false; - nsCOMPtr control(do_QueryInterface(aContent)); - mozilla::dom::Element* formElement = control->GetFormElement(); - nsCOMPtr form; - if (control) { - // is this a form and does it have a default submit element? - if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) { - willSubmit = true; - // is this an html form and does it only have a single text input element? - } else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() && - static_cast(formElement)->HasSingleTextControl()) { - willSubmit = true; - } + InputContext context; + context.mIMEState = aState; + + if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML && + (aContent->Tag() == nsGkAtoms::input || + aContent->Tag() == nsGkAtoms::textarea)) { + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, + context.mHTMLInputType); + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint, + context.mActionHint); + + // if we don't have an action hint and return won't submit the form use "next" + if (context.mActionHint.IsEmpty() && aContent->Tag() == nsGkAtoms::input) { + bool willSubmit = false; + nsCOMPtr control(do_QueryInterface(aContent)); + mozilla::dom::Element* formElement = control->GetFormElement(); + nsCOMPtr form; + if (control) { + // is this a form and does it have a default submit element? + if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) { + willSubmit = true; + // is this an html form and does it only have a single text input element? + } else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() && + static_cast(formElement)->HasSingleTextControl()) { + willSubmit = true; } - context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH - ? NS_LITERAL_STRING("search") - : NS_LITERAL_STRING("go") - : formElement - ? NS_LITERAL_STRING("next") - : EmptyString()); } + context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH + ? NS_LITERAL_STRING("search") + : NS_LITERAL_STRING("go") + : formElement + ? NS_LITERAL_STRING("next") + : EmptyString()); } - - if (XRE_GetProcessType() == GeckoProcessType_Content) { - context.mReason = aReason | IMEContext::FOCUS_FROM_CONTENT_PROCESS; - } else { - context.mReason = aReason; - } - - aWidget->SetInputMode(context); - - nsContentUtils::AddScriptRunner(new IMEEnabledStateChangedEvent(state)); } - if (aState & nsIContent::IME_STATUS_MASK_OPENED) { - bool open = !!(aState & nsIContent::IME_STATUS_OPEN); - aWidget->SetIMEOpenState(open); + + // XXX I think that we should use nsContentUtils::IsCallerChrome() instead + // of the process type. + if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN && + XRE_GetProcessType() != GeckoProcessType_Content) { + aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME; + } + + aWidget->SetInputContext(context, aAction); + if (oldContext.mIMEState.mEnabled != context.mIMEState.mEnabled) { + nsContentUtils::AddScriptRunner( + new IMEEnabledStateChangedEvent(context.mIMEState.mEnabled)); } } diff --git a/content/events/src/nsIMEStateManager.h b/content/events/src/nsIMEStateManager.h index 9b6d01f537d..e77078f91c1 100644 --- a/content/events/src/nsIMEStateManager.h +++ b/content/events/src/nsIMEStateManager.h @@ -40,11 +40,12 @@ #define nsIMEStateManager_h__ #include "nscore.h" +#include "nsIWidget.h" class nsIContent; +class nsIDOMMouseEvent; class nsPIDOMWindow; class nsPresContext; -class nsIWidget; class nsTextStateManager; class nsISelection; @@ -54,13 +55,23 @@ class nsISelection; class nsIMEStateManager { +protected: + typedef mozilla::widget::IMEState IMEState; + typedef mozilla::widget::InputContext InputContext; + typedef mozilla::widget::InputContextAction InputContextAction; + public: static nsresult OnDestroyPresContext(nsPresContext* aPresContext); static nsresult OnRemoveContent(nsPresContext* aPresContext, nsIContent* aContent); + /** + * OnChangeFocus() should be called when focused content is changed or + * IME enabled state is changed. If focus isn't actually changed and IME + * enabled state isn't changed, this will do nothing. + */ static nsresult OnChangeFocus(nsPresContext* aPresContext, nsIContent* aContent, - PRUint32 aReason); + InputContextAction::Cause aCause); static void OnInstalledMenuKeyboardListener(bool aInstalling); // These two methods manage focus and selection/text observers. @@ -85,14 +96,27 @@ public: // isn't changed by the new state, this method does nothing. // Note that this method changes the IME state of the active element in the // widget. So, the caller must have focus. - // aNewIMEState must have an enabled state of nsIContent::IME_STATUS_*. - // And optionally, it can have an open state of nsIContent::IME_STATUS_*. - static void UpdateIMEState(PRUint32 aNewIMEState, nsIContent* aContent); + static void UpdateIMEState(const IMEState &aNewIMEState, + nsIContent* aContent); + + // This method is called when user clicked in an editor. + // aContent must be: + // If the editor is for or