diff --git a/dom/base/TextInputProcessor.cpp b/dom/base/TextInputProcessor.cpp index 5d9da4dd9a7..a8365ed9cb3 100644 --- a/dom/base/TextInputProcessor.cpp +++ b/dom/base/TextInputProcessor.cpp @@ -596,6 +596,38 @@ TextInputProcessor::Keyup(nsIDOMKeyEvent* aDOMKeyEvent, return NS_OK; } +NS_IMETHODIMP +TextInputProcessor::GetModifierState(const nsAString& aModifierKeyName, + bool* aActive) +{ + MOZ_RELEASE_ASSERT(aActive, "aActive must not be null"); + MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); + if (!mModifierKeyDataArray) { + *aActive = false; + return NS_OK; + } + Modifiers activeModifiers = mModifierKeyDataArray->GetActiveModifiers(); + Modifiers modifier = WidgetInputEvent::GetModifier(aModifierKeyName); + *aActive = ((activeModifiers & modifier) != 0); + return NS_OK; +} + +NS_IMETHODIMP +TextInputProcessor::ShareModifierStateOf(nsITextInputProcessor* aOther) +{ + MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); + if (!aOther) { + mModifierKeyDataArray = nullptr; + return NS_OK; + } + TextInputProcessor* other = static_cast(aOther); + if (!other->mModifierKeyDataArray) { + other->mModifierKeyDataArray = new ModifierKeyDataArray(); + } + mModifierKeyDataArray = other->mModifierKeyDataArray; + return NS_OK; +} + /****************************************************************************** * TextInputProcessor::ModifierKeyData ******************************************************************************/ diff --git a/dom/base/TextInputProcessor.h b/dom/base/TextInputProcessor.h index 003385fd1a9..1544fb5ce1a 100644 --- a/dom/base/TextInputProcessor.h +++ b/dom/base/TextInputProcessor.h @@ -8,6 +8,7 @@ #include "mozilla/EventForwards.h" #include "mozilla/TextEventDispatcherListener.h" +#include "nsAutoPtr.h" #include "nsITextInputProcessor.h" #include "nsITextInputProcessorCallback.h" #include "nsTArray.h" @@ -78,33 +79,51 @@ private: class ModifierKeyDataArray : public nsTArray { + NS_INLINE_DECL_REFCOUNTING(ModifierKeyDataArray) + public: Modifiers GetActiveModifiers() const; void ActivateModifierKey(const ModifierKeyData& aModifierKeyData); void InactivateModifierKey(const ModifierKeyData& aModifierKeyData); void ToggleModifierKey(const ModifierKeyData& aModifierKeyData); + + private: + virtual ~ModifierKeyDataArray() { } }; Modifiers GetActiveModifiers() const { - return mModifierKeyDataArray.GetActiveModifiers(); + return mModifierKeyDataArray ? + mModifierKeyDataArray->GetActiveModifiers() : 0; + } + void EnsureModifierKeyDataArray() + { + if (mModifierKeyDataArray) { + return; + } + mModifierKeyDataArray = new ModifierKeyDataArray(); } void ActivateModifierKey(const ModifierKeyData& aModifierKeyData) { - mModifierKeyDataArray.ActivateModifierKey(aModifierKeyData); + EnsureModifierKeyDataArray(); + mModifierKeyDataArray->ActivateModifierKey(aModifierKeyData); } void InactivateModifierKey(const ModifierKeyData& aModifierKeyData) { - mModifierKeyDataArray.InactivateModifierKey(aModifierKeyData); + if (!mModifierKeyDataArray) { + return; + } + mModifierKeyDataArray->InactivateModifierKey(aModifierKeyData); } void ToggleModifierKey(const ModifierKeyData& aModifierKeyData) { - mModifierKeyDataArray.ToggleModifierKey(aModifierKeyData); + EnsureModifierKeyDataArray(); + mModifierKeyDataArray->ToggleModifierKey(aModifierKeyData); } TextEventDispatcher* mDispatcher; // [Weak] nsCOMPtr mCallback; - ModifierKeyDataArray mModifierKeyDataArray; + nsRefPtr mModifierKeyDataArray; bool mForTests; }; diff --git a/dom/base/test/chrome/window_nsITextInputProcessor.xul b/dom/base/test/chrome/window_nsITextInputProcessor.xul index e4c4a9d6a9c..52a91e587ca 100644 --- a/dom/base/test/chrome/window_nsITextInputProcessor.xul +++ b/dom/base/test/chrome/window_nsITextInputProcessor.xul @@ -1155,6 +1155,11 @@ function runKeyTests() } // Modifier state tests + var sharedTIP = createTIP(); + ok(sharedTIP.beginInputTransactionForTests(otherWindow), + description + "sharedTIP.beginInputTransactionForTests(otherWindow) should return true"); + TIP.shareModifierStateOf(sharedTIP); + var independentTIP = createTIP(); const kModifierKeys = [ { key: "Alt", code: "AltLeft", isLockable: false }, { key: "Alt", code: "AltRight", isLockable: false }, @@ -1204,6 +1209,18 @@ function runKeyTests() } } + function checkAllTIPModifiers(aTestDesc, aModifiers) + { + for (var i = 0; i < kModifiers.length; i++) { + is(TIP.getModifierState(kModifiers[i]), aModifiers.indexOf(kModifiers[i]) >= 0, + aTestDesc + ", TIP.getModifierState(\"" + kModifiers[i] + "\") returns wrong value"); + is(sharedTIP.getModifierState(kModifiers[i]), TIP.getModifierState(kModifiers[i]), + aTestDesc + ", sharedTIP.getModifierState(\"" + kModifiers[i] + "\") returns different value from TIP"); + is(independentTIP.getModifierState(kModifiers[i]), false, + aTestDesc + ", independentTIP.getModifierState(\"" + kModifiers[i] + "\") should return false"); + } + } + // First, all modifiers must be false. reset(); doPreventDefaults = [ "keypress" ]; @@ -1224,9 +1241,13 @@ function runKeyTests() var testDesc = "A modifier key \"" + kModifierKeys[i].key + "\" (\"" + kModifierKeys[i].code + "\") and a printable key"; if (!kModifierKeys[i].isLockable) { TIP.keydown(modKey); + checkAllTIPModifiers(testDesc + ", \"" + kModifierKeys[i].key + "\" keydown", [ kModifierKeys[i].key ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ kModifierKeys[i].key ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ kModifierKeys[i].key ]); TIP.keyup(modKey); + checkAllTIPModifiers(testDesc + ", \"" + kModifierKeys[i].key + "\" keyup", [ ]); is(events.length, 5, description + testDesc + " should cause 5 events"); checkModifiers(testDesc, events[0], "keydown", kModifierKeys[i].key, kModifierKeys[i].code, [ kModifierKeys[i].key ]); @@ -1236,11 +1257,17 @@ function runKeyTests() checkModifiers(testDesc, events[4], "keyup", kModifierKeys[i].key, kModifierKeys[i].code, [ ]); } else { TIP.keydown(modKey); + checkAllTIPModifiers(testDesc + ", \"" + kModifierKeys[i].key + "\" first keydown", [ kModifierKeys[i].key ]); TIP.keyup(modKey); + checkAllTIPModifiers(testDesc + ", \"" + kModifierKeys[i].key + "\" first keyup", [ kModifierKeys[i].key ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ kModifierKeys[i].key ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ kModifierKeys[i].key ]); TIP.keydown(modKey); + checkAllTIPModifiers(testDesc + ", \"" + kModifierKeys[i].key + "\" second keydown", [ ]); TIP.keyup(modKey); + checkAllTIPModifiers(testDesc + ", \"" + kModifierKeys[i].key + "\" second keyup", [ ]); is(events.length, 7, description + testDesc + " should cause 7 events"); checkModifiers(testDesc, events[0], "keydown", kModifierKeys[i].key, kModifierKeys[i].code, [ kModifierKeys[i].key ]); @@ -1258,18 +1285,27 @@ function runKeyTests() var shiftRight = new KeyboardEvent("", { key: "Shift", code: "ShiftRight" }); var shiftVirtual = new KeyboardEvent("", { key: "Shift", code: "" }); var altGrVirtual = new KeyboardEvent("", { key: "AltGraph", code: "" }); + var ctrlVirtual = new KeyboardEvent("", { key: "Control", code: "" }); var testDesc = "ShiftLeft press -> ShiftRight press -> ShiftRight release -> ShiftLeft release"; reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keydown", [ "Shift" ]); TIP.keydown(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keydown", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift" ]); TIP.keyup(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keyup", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Right-Shift keyup)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Right-Shift keyup)", [ "Shift" ]); TIP.keyup(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keyup", [ ]); is(events.length, 10, description + testDesc + " should cause 10 events"); @@ -1288,13 +1324,21 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keydown", [ "Shift" ]); TIP.keydown(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keydown", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift" ]); TIP.keyup(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keyup", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Left-Shift keyup)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Left-Shift keyup)", [ "Shift" ]); TIP.keyup(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keyup", [ ]); is(events.length, 10, description + testDesc + " should cause 10 events"); @@ -1313,13 +1357,21 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keydown", [ "Shift" ]); TIP.keydown(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keydown", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift" ]); TIP.keyup(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keyup", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Virtual-Shift keyup)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Virtual-Shift keyup)", [ "Shift" ]); TIP.keyup(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keyup", [ ]); is(events.length, 10, description + testDesc + " should cause 10 events"); @@ -1338,13 +1390,21 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keydown", [ "Shift" ]); TIP.keydown(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keydown", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift" ]); TIP.keyup(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keyup", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Right-Shift keyup)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Right-Shift keyup)", [ "Shift" ]); TIP.keyup(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keyup", [ ]); is(events.length, 10, description + testDesc + " should cause 10 events"); @@ -1363,16 +1423,27 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keydown", [ "Shift" ]); TIP.keydown(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keydown", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift" ]); TIP.keyup(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keyup", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Virtual-Shift keyup)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Virtual-Shift keyup)", [ "Shift" ]); TIP.keyup(shiftRight); + checkAllTIPModifiers(testDesc + ", Right-Shift keyup again", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Virtual-Shift keyup again)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Virtual-Shift keyup again)", [ "Shift" ]); TIP.keyup(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keyup", [ ]); is(events.length, 14, description + testDesc + " should cause 14 events"); @@ -1395,15 +1466,25 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keydown", [ "Shift" ]); TIP.keydown(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keydown again", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift" ]); TIP.keyup(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keyup", [ ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Left-Shift keyup)", [ ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Left-Shift keyup)", [ ]); TIP.keyup(shiftLeft); + checkAllTIPModifiers(testDesc + ", Left-Shift keyup again", [ ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Left-Shift keyup again)", [ ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Left-Shift keyup again)", [ ]); is(events.length, 13, description + testDesc + " should cause 13 events"); @@ -1425,13 +1506,21 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keydown", [ "Shift" ]); TIP.keydown(altGrVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-AltGraph keydown", [ "Shift", "AltGraph" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift", "AltGraph" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift", "AltGraph" ]); TIP.keyup(altGrVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-AltGraph keyup", [ "Shift" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Virtual-AltGraph keyup)", [ "Shift" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Virtual-AltGraph keyup)", [ "Shift" ]); TIP.keyup(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keyup", [ ]); is(events.length, 10, description + testDesc + " should cause 10 events"); @@ -1450,13 +1539,21 @@ function runKeyTests() reset(); doPreventDefaults = [ "keypress" ]; TIP.keydown(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keydown", [ "Shift" ]); TIP.keydown(altGrVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-AltGraph keydown", [ "Shift", "AltGraph" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown", [ "Shift", "AltGraph" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup", [ "Shift", "AltGraph" ]); TIP.keyup(shiftVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-Shift keyup", [ "AltGraph" ]); TIP.keydown(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keydown (after Virtual-Shift keyup)", [ "AltGraph" ]); TIP.keyup(keyA); + checkAllTIPModifiers(testDesc + ", \"a\" keyup (after Virtual-Shift keyup)", [ "AltGraph" ]); TIP.keyup(altGrVirtual); + checkAllTIPModifiers(testDesc + ", Virtual-AltGraph keyup", [ ]); is(events.length, 10, description + testDesc + " should cause 10 events"); @@ -1471,6 +1568,39 @@ function runKeyTests() checkModifiers(testDesc, events[8], "keyup", "a", "KeyA", [ "AltGraph" ]); checkModifiers(testDesc, events[9], "keyup", "AltGraph", "", [ ]); + // shareModifierStateOf(null) should cause resetting the modifier state + function checkTIPModifiers(aTestDesc, aTIP, aModifiers) + { + for (var i = 0; i < kModifiers.length; i++) { + is(aTIP.getModifierState(kModifiers[i]), aModifiers.indexOf(kModifiers[i]) >= 0, + description + aTestDesc + ", aTIP.getModifierState(\"" + kModifiers[i] + "\") returns wrong value"); + } + } + TIP.keydown(shiftVirtual); + TIP.keydown(altGrVirtual); + sharedTIP.shareModifierStateOf(null); + checkTIPModifiers("sharedTIP.sharedModifierStateOf(null) shouldn't cause TIP's modifiers reset", TIP, [ "Shift", "AltGraph" ]); + checkTIPModifiers("sharedTIP.sharedModifierStateOf(null) should cause sharedTIP modifiers reset", sharedTIP, [ ]); + + // sharedTIP.shareModifierStateOf(null) should be unlinked from TIP. + TIP.keydown(ctrlVirtual); + checkTIPModifiers("TIP.keydown(ctrlVirtual) should cause TIP's modifiers set", TIP, [ "Shift", "AltGraph", "Control" ]); + checkTIPModifiers("TIP.keydown(ctrlVirtual) shouldn't cause sharedTIP modifiers set", sharedTIP, [ ]); + + // beginInputTransactionForTests() shouldn't cause modifier state reset. + ok(TIP.beginInputTransactionForTests(otherWindow), + description + "TIP.beginInputTransactionForTests(otherWindow) should return true"); + checkTIPModifiers("TIP.beginInputTransactionForTests(otherWindow) shouldn't cause TIP's modifiers set", TIP, [ "Shift", "AltGraph", "Control" ]); + TIP.keyup(shiftLeft); + TIP.keyup(altGrVirtual); + TIP.keyup(ctrlVirtual); + checkTIPModifiers("TIP should keep modifier's physical key state", TIP, [ "Shift" ]); + ok(TIP.beginInputTransactionForTests(window), + description + "TIP.beginInputTransactionForTests(window) should return true"); + checkTIPModifiers("TIP.beginInputTransactionForTests(window) shouldn't cause TIP's modifiers set", TIP, [ "Shift" ]); + TIP.keyup(shiftVirtual); + checkTIPModifiers("TIP should keep modifier's physical key state", TIP, [ ]); + window.removeEventListener("keydown", handler, false); window.removeEventListener("keypress", handler, false); window.removeEventListener("keyup", handler, false); diff --git a/dom/events/UIEvent.cpp b/dom/events/UIEvent.cpp index 64e833dfce5..9a0dbeeadae 100644 --- a/dom/events/UIEvent.cpp +++ b/dom/events/UIEvent.cpp @@ -452,52 +452,7 @@ UIEvent::GetModifierStateInternal(const nsAString& aKey) { WidgetInputEvent* inputEvent = mEvent->AsInputEvent(); MOZ_ASSERT(inputEvent, "mEvent must be WidgetInputEvent or derived class"); - if (aKey.EqualsLiteral("Accel")) { - return inputEvent->IsAccel(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SHIFT)) { - return inputEvent->IsShift(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_CONTROL)) { - return inputEvent->IsControl(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_META)) { - return inputEvent->IsMeta(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_ALT)) { - return inputEvent->IsAlt(); - } - - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_ALTGRAPH)) { - return inputEvent->IsAltGraph(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_OS)) { - return inputEvent->IsOS(); - } - - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_CAPSLOCK)) { - return inputEvent->IsCapsLocked(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_NUMLOCK)) { - return inputEvent->IsNumLocked(); - } - - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_FN)) { - return inputEvent->IsFn(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_FNLOCK)) { - return inputEvent->IsFnLocked(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SCROLLLOCK)) { - return inputEvent->IsScrollLocked(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SYMBOL)) { - return inputEvent->IsSymbol(); - } - if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SYMBOLLOCK)) { - return inputEvent->IsSymbolLocked(); - } - return false; + return ((inputEvent->modifiers & WidgetInputEvent::GetModifier(aKey)) != 0); } } // namespace dom diff --git a/dom/interfaces/base/nsITextInputProcessor.idl b/dom/interfaces/base/nsITextInputProcessor.idl index 3b527bd6f61..5fa5f21a93b 100644 --- a/dom/interfaces/base/nsITextInputProcessor.idl +++ b/dom/interfaces/base/nsITextInputProcessor.idl @@ -224,7 +224,7 @@ interface nsITextInputProcessorCallback; * TIP.keyup(leftShift); */ -[scriptable, builtinclass, uuid(16144d6e-a97a-4733-aa6a-3a1287cfe539)] +[scriptable, builtinclass, uuid(c8b5d3fb-5bed-4b77-b67f-77aee6ac5081)] interface nsITextInputProcessor : nsISupports { /** @@ -464,6 +464,28 @@ interface nsITextInputProcessor : nsISupports [optional_argc] boolean keyup(in nsIDOMKeyEvent aKeyboardEvent, [optional] in unsigned long aKeyFlags); + + /** + * getModifierState() returns modifier state managed by this instance. + * + * @param aModifier One of modifier key names. This doesn't support + * virtual modifiers like "Accel". + * @return true if the modifier key is active. Otherwise, + * false. + */ + boolean getModifierState(in DOMString aModifierKey); + + /** + * shareModifierStateOf() makes the instance shares modifier state of + * another instance. When this is called, the instance refers the modifier + * state of another instance. After that, changes to either this and the + * other instance's modifier state is synchronized. + * + * @param aOther Another instance which will be referred by the + * instance. If this is null, the instance restarts + * to manage modifier state independently. + */ + void shareModifierStateOf(in nsITextInputProcessor aOther); }; %{C++ diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index bb8ffdc9f99..237fc8289ee 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -1016,6 +1016,11 @@ public: */ static Modifier AccelModifier(); + /** + * GetModifier() returns a modifier flag which is activated by aDOMKeyName. + */ + static Modifier GetModifier(const nsAString& aDOMKeyName); + // true indicates the accel key on the environment is down bool IsAccel() const { diff --git a/widget/WidgetEventImpl.cpp b/widget/WidgetEventImpl.cpp index 19201a2abf0..bb1fe031f2f 100644 --- a/widget/WidgetEventImpl.cpp +++ b/widget/WidgetEventImpl.cpp @@ -254,6 +254,17 @@ WidgetEvent::IsAllowedToDispatchDOMEvent() const * mozilla::WidgetInputEvent ******************************************************************************/ +/* static */ +Modifier +WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName) +{ + if (aDOMKeyName.EqualsLiteral("Accel")) { + return AccelModifier(); + } + KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName); + return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex); +} + /* static */ Modifier WidgetInputEvent::AccelModifier()