зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1423098 - Drop support for SMIL accessKey; r=dholbert
MozReview-Commit-ID: Evrl4St3QSD --HG-- extra : rebase_source : b5fc6574efe9e48f70c2d3affa0ed782e1909031
This commit is contained in:
Родитель
0279523bb7
Коммит
f5dff74bc2
|
@ -269,55 +269,6 @@ ParseOptionalOffset(RangedPtr<const char16_t>& aIter,
|
|||
ParseOffsetValue(aIter, aEnd, aResult);
|
||||
}
|
||||
|
||||
bool
|
||||
ParseAccessKey(const nsAString& aSpec, nsSMILTimeValueSpecParams& aResult)
|
||||
{
|
||||
MOZ_ASSERT(StringBeginsWith(aSpec, ACCESSKEY_PREFIX_CC) ||
|
||||
StringBeginsWith(aSpec, ACCESSKEY_PREFIX_LC),
|
||||
"Calling ParseAccessKey on non-accesskey-type spec");
|
||||
|
||||
nsSMILTimeValueSpecParams result;
|
||||
result.mType = nsSMILTimeValueSpecParams::ACCESSKEY;
|
||||
|
||||
MOZ_ASSERT(ACCESSKEY_PREFIX_LC.Length() == ACCESSKEY_PREFIX_CC.Length(),
|
||||
"Case variations for accesskey prefix differ in length");
|
||||
|
||||
RangedPtr<const char16_t> iter(SVGContentUtils::GetStartRangedPtr(aSpec));
|
||||
RangedPtr<const char16_t> end(SVGContentUtils::GetEndRangedPtr(aSpec));
|
||||
|
||||
iter += ACCESSKEY_PREFIX_LC.Length();
|
||||
|
||||
// Expecting at least <accesskey> + ')'
|
||||
if (end - iter < 2)
|
||||
return false;
|
||||
|
||||
uint32_t c = *iter++;
|
||||
|
||||
// Process 32-bit codepoints
|
||||
if (NS_IS_HIGH_SURROGATE(c)) {
|
||||
if (end - iter < 2) // Expecting at least low-surrogate + ')'
|
||||
return false;
|
||||
uint32_t lo = *iter++;
|
||||
if (!NS_IS_LOW_SURROGATE(lo))
|
||||
return false;
|
||||
c = SURROGATE_TO_UCS4(c, lo);
|
||||
// XML 1.1 says that 0xFFFE and 0xFFFF are not valid characters
|
||||
} else if (NS_IS_LOW_SURROGATE(c) || c == 0xFFFE || c == 0xFFFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result.mRepeatIterationOrAccessKey = c;
|
||||
|
||||
if (*iter++ != ')')
|
||||
return false;
|
||||
|
||||
if (!ParseOptionalOffset(iter, end, &result.mOffset) || iter != end) {
|
||||
return false;
|
||||
}
|
||||
aResult = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MoveToNextToken(RangedPtr<const char16_t>& aIter,
|
||||
const RangedPtr<const char16_t>& aEnd,
|
||||
|
@ -453,7 +404,7 @@ ParseElementBaseTimeValueSpec(const nsAString& aSpec,
|
|||
return false;
|
||||
}
|
||||
result.mType = nsSMILTimeValueSpecParams::REPEAT;
|
||||
result.mRepeatIterationOrAccessKey = repeatValue;
|
||||
result.mRepeatIteration = repeatValue;
|
||||
// element-name.event-symbol
|
||||
} else {
|
||||
atom = ConvertTokenToAtom(token2, requiresUnescaping);
|
||||
|
@ -687,7 +638,7 @@ nsSMILParserUtils::ParseTimeValueSpecParams(const nsAString& aSpec,
|
|||
// accesskey type
|
||||
if (StringBeginsWith(spec, ACCESSKEY_PREFIX_LC) ||
|
||||
StringBeginsWith(spec, ACCESSKEY_PREFIX_CC)) {
|
||||
return ParseAccessKey(spec, aResult);
|
||||
return false; // accesskey is not supported
|
||||
}
|
||||
|
||||
// event, syncbase, or repeat
|
||||
|
|
|
@ -78,8 +78,6 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
|
|||
// Fill in the event symbol to simplify handling later
|
||||
if (mParams.mType == nsSMILTimeValueSpecParams::REPEAT) {
|
||||
mParams.mEventSymbol = nsGkAtoms::repeatEvent;
|
||||
} else if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
|
||||
mParams.mEventSymbol = nsGkAtoms::keypress;
|
||||
}
|
||||
|
||||
ResolveReferences(aContextNode);
|
||||
|
@ -112,10 +110,6 @@ nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
|
|||
} else if (mParams.mType == nsSMILTimeValueSpecParams::EVENT) {
|
||||
Element* target = mOwner->GetTargetElement();
|
||||
mReferencedElement.ResetWithElement(target);
|
||||
} else if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
|
||||
nsIDocument* doc = aContextNode->GetUncomposedDoc();
|
||||
MOZ_ASSERT(doc, "We are in the document but current doc is null");
|
||||
mReferencedElement.ResetWithElement(doc->GetRootElement());
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Syncbase or repeat spec without ID");
|
||||
}
|
||||
|
@ -126,8 +120,7 @@ bool
|
|||
nsSMILTimeValueSpec::IsEventBased() const
|
||||
{
|
||||
return mParams.mType == nsSMILTimeValueSpecParams::EVENT ||
|
||||
mParams.mType == nsSMILTimeValueSpecParams::REPEAT ||
|
||||
mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY;
|
||||
mParams.mType == nsSMILTimeValueSpecParams::REPEAT;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -239,7 +232,6 @@ nsSMILTimeValueSpec::UpdateReferencedElement(Element* aFrom, Element* aTo)
|
|||
|
||||
case nsSMILTimeValueSpecParams::EVENT:
|
||||
case nsSMILTimeValueSpecParams::REPEAT:
|
||||
case nsSMILTimeValueSpecParams::ACCESSKEY:
|
||||
RegisterEventListener(aTo);
|
||||
break;
|
||||
|
||||
|
@ -318,9 +310,10 @@ nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
|
|||
mEventListener = new EventListener(this);
|
||||
}
|
||||
|
||||
EventListenerManager* elm = GetEventListenerManager(aTarget);
|
||||
if (!elm)
|
||||
EventListenerManager* elm = aTarget->GetOrCreateListenerManager();
|
||||
if (!elm) {
|
||||
return;
|
||||
}
|
||||
|
||||
elm->AddEventListenerByType(mEventListener,
|
||||
nsDependentAtomString(mParams.mEventSymbol),
|
||||
|
@ -330,42 +323,20 @@ nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
|
|||
void
|
||||
nsSMILTimeValueSpec::UnregisterEventListener(Element* aTarget)
|
||||
{
|
||||
if (!aTarget || !mEventListener)
|
||||
if (!aTarget || !mEventListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventListenerManager* elm = GetEventListenerManager(aTarget);
|
||||
if (!elm)
|
||||
EventListenerManager* elm = aTarget->GetOrCreateListenerManager();
|
||||
if (!elm) {
|
||||
return;
|
||||
}
|
||||
|
||||
elm->RemoveEventListenerByType(mEventListener,
|
||||
nsDependentAtomString(mParams.mEventSymbol),
|
||||
AllEventsAtSystemGroupBubble());
|
||||
}
|
||||
|
||||
EventListenerManager*
|
||||
nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget)
|
||||
{
|
||||
MOZ_ASSERT(aTarget, "null target; can't get EventListenerManager");
|
||||
|
||||
nsCOMPtr<EventTarget> target;
|
||||
|
||||
if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
|
||||
nsIDocument* doc = aTarget->GetUncomposedDoc();
|
||||
if (!doc)
|
||||
return nullptr;
|
||||
nsPIDOMWindowOuter* win = doc->GetWindow();
|
||||
if (!win)
|
||||
return nullptr;
|
||||
target = do_QueryInterface(win);
|
||||
} else {
|
||||
target = aTarget;
|
||||
}
|
||||
if (!target)
|
||||
return nullptr;
|
||||
|
||||
return target->GetOrCreateListenerManager();
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
@ -381,8 +352,10 @@ nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
|
|||
if (!container)
|
||||
return;
|
||||
|
||||
if (!CheckEventDetail(aEvent))
|
||||
if (mParams.mType == nsSMILTimeValueSpecParams::REPEAT &&
|
||||
!CheckRepeatEventDetail(aEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsSMILTime currentTime = container->GetCurrentTime();
|
||||
nsSMILTimeValue newTime(currentTime);
|
||||
|
@ -396,23 +369,6 @@ nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
|
|||
mOwner->AddInstanceTime(newInstance, mIsBegin);
|
||||
}
|
||||
|
||||
bool
|
||||
nsSMILTimeValueSpec::CheckEventDetail(nsIDOMEvent *aEvent)
|
||||
{
|
||||
switch (mParams.mType)
|
||||
{
|
||||
case nsSMILTimeValueSpecParams::REPEAT:
|
||||
return CheckRepeatEventDetail(aEvent);
|
||||
|
||||
case nsSMILTimeValueSpecParams::ACCESSKEY:
|
||||
return CheckAccessKeyEventDetail(aEvent);
|
||||
|
||||
default:
|
||||
// nothing to check
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsSMILTimeValueSpec::CheckRepeatEventDetail(nsIDOMEvent *aEvent)
|
||||
{
|
||||
|
@ -424,63 +380,7 @@ nsSMILTimeValueSpec::CheckRepeatEventDetail(nsIDOMEvent *aEvent)
|
|||
|
||||
int32_t detail;
|
||||
timeEvent->GetDetail(&detail);
|
||||
return detail > 0 && (uint32_t)detail == mParams.mRepeatIterationOrAccessKey;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSMILTimeValueSpec::CheckAccessKeyEventDetail(nsIDOMEvent *aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
|
||||
if (!keyEvent) {
|
||||
NS_WARNING("Received an accesskey event that was not a DOMKeyEvent");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore the key event if any modifier keys are pressed UNLESS we're matching
|
||||
// on the charCode in which case we ignore the state of the shift and alt keys
|
||||
// since they might be needed to generate the character in question.
|
||||
bool isCtrl;
|
||||
bool isMeta;
|
||||
keyEvent->GetCtrlKey(&isCtrl);
|
||||
keyEvent->GetMetaKey(&isMeta);
|
||||
if (isCtrl || isMeta)
|
||||
return false;
|
||||
|
||||
uint32_t code;
|
||||
keyEvent->GetCharCode(&code);
|
||||
if (code)
|
||||
return code == mParams.mRepeatIterationOrAccessKey;
|
||||
|
||||
// Only match on the keyCode if it corresponds to some ASCII character that
|
||||
// does not produce a charCode.
|
||||
// In this case we can safely bail out if either alt or shift is pressed since
|
||||
// they won't already be incorporated into the keyCode unlike the charCode.
|
||||
bool isAlt;
|
||||
bool isShift;
|
||||
keyEvent->GetAltKey(&isAlt);
|
||||
keyEvent->GetShiftKey(&isShift);
|
||||
if (isAlt || isShift)
|
||||
return false;
|
||||
|
||||
keyEvent->GetKeyCode(&code);
|
||||
switch (code)
|
||||
{
|
||||
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
|
||||
return mParams.mRepeatIterationOrAccessKey == 0x08;
|
||||
|
||||
case nsIDOMKeyEvent::DOM_VK_RETURN:
|
||||
return mParams.mRepeatIterationOrAccessKey == 0x0A ||
|
||||
mParams.mRepeatIterationOrAccessKey == 0x0D;
|
||||
|
||||
case nsIDOMKeyEvent::DOM_VK_ESCAPE:
|
||||
return mParams.mRepeatIterationOrAccessKey == 0x1B;
|
||||
|
||||
case nsIDOMKeyEvent::DOM_VK_DELETE:
|
||||
return mParams.mRepeatIterationOrAccessKey == 0x7F;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return detail > 0 && (uint32_t)detail == mParams.mRepeatIteration;
|
||||
}
|
||||
|
||||
nsSMILTimeValue
|
||||
|
|
|
@ -28,7 +28,7 @@ class EventListenerManager;
|
|||
//
|
||||
// An individual element of a 'begin' or 'end' attribute, e.g. '5s', 'a.end'.
|
||||
// This class handles the parsing of such specifications and performs the
|
||||
// necessary event handling (for event, repeat, and accesskey specifications)
|
||||
// necessary event handling (for event and repeat specifications)
|
||||
// and synchronisation (for syncbase specifications).
|
||||
//
|
||||
// For an overview of how this class is related to other SMIL time classes see
|
||||
|
@ -70,11 +70,8 @@ protected:
|
|||
bool IsWhitelistedEvent();
|
||||
void RegisterEventListener(Element* aElement);
|
||||
void UnregisterEventListener(Element* aElement);
|
||||
mozilla::EventListenerManager* GetEventListenerManager(Element* aElement);
|
||||
void HandleEvent(nsIDOMEvent* aEvent);
|
||||
bool CheckEventDetail(nsIDOMEvent* aEvent);
|
||||
bool CheckRepeatEventDetail(nsIDOMEvent* aEvent);
|
||||
bool CheckAccessKeyEventDetail(nsIDOMEvent* aEvent);
|
||||
nsSMILTimeValue ConvertBetweenTimeContainers(const nsSMILTimeValue& aSrcTime,
|
||||
const nsSMILTimeContainer* aSrcContainer);
|
||||
bool ApplyOffset(nsSMILTimeValue& aTime) const;
|
||||
|
|
|
@ -20,10 +20,9 @@ class nsSMILTimeValueSpecParams
|
|||
{
|
||||
public:
|
||||
nsSMILTimeValueSpecParams()
|
||||
:
|
||||
mType(INDEFINITE),
|
||||
mSyncBegin(false),
|
||||
mRepeatIterationOrAccessKey(0)
|
||||
: mType(INDEFINITE)
|
||||
, mSyncBegin(false)
|
||||
, mRepeatIteration(0)
|
||||
{ }
|
||||
|
||||
// The type of value this specification describes
|
||||
|
@ -32,7 +31,6 @@ public:
|
|||
SYNCBASE,
|
||||
EVENT,
|
||||
REPEAT,
|
||||
ACCESSKEY,
|
||||
WALLCLOCK,
|
||||
INDEFINITE
|
||||
} mType;
|
||||
|
@ -42,7 +40,6 @@ public:
|
|||
// - type SYNCBASE: the timebase's begin or end time
|
||||
// - type EVENT: the event time
|
||||
// - type REPEAT: the repeat time
|
||||
// - type ACCESSKEY: the keypress time
|
||||
// It is not used for WALLCLOCK or INDEFINITE times
|
||||
nsSMILTimeValue mOffset;
|
||||
|
||||
|
@ -60,9 +57,9 @@ public:
|
|||
// Only used for SYNCBASE types.
|
||||
bool mSyncBegin;
|
||||
|
||||
// The repeat iteration (type=REPEAT) or access key (type=ACCESSKEY) to
|
||||
// respond to.
|
||||
uint32_t mRepeatIterationOrAccessKey;
|
||||
// The repeat iteration to respond to.
|
||||
// Only used for mType=REPEAT.
|
||||
uint32_t mRepeatIteration;
|
||||
};
|
||||
|
||||
#endif // NS_SMILTIMEVALUESPECPARAMS_H_
|
||||
|
|
|
@ -17,170 +17,26 @@
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
/** Test for SMIL accessKey support **/
|
||||
/** Test for lack of SMIL accessKey support **/
|
||||
|
||||
const gSvgns = "http://www.w3.org/2000/svg";
|
||||
var gSvg = document.getElementById("svg");
|
||||
const gSvgns = 'http://www.w3.org/2000/svg';
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function main()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
testBeginValueIsNotSupported('accessKey(a)');
|
||||
testBeginValueIsNotSupported('accesskey(a)');
|
||||
|
||||
// Basic syntax
|
||||
testOk('accessKey(a)', 'a');
|
||||
testOk(' accessKey(a) ', 'a');
|
||||
testNotOk('accessKey (a)', 'a');
|
||||
testNotOk('accessKey( a)', 'a');
|
||||
testNotOk('accessKey(a )', 'a');
|
||||
testNotOk('accessKey(a)', 'b');
|
||||
testNotOk('accessKey()', ' ');
|
||||
|
||||
// Test the test framework itself
|
||||
testOk('accessKey(a)', 97);
|
||||
|
||||
// Allow for either accessKey (SVG / SMIL Animation) or accesskey (SMIL2+)
|
||||
testOk('accesskey(a)', 'a');
|
||||
|
||||
// Offset
|
||||
testOk('accessKey(a)+0s', 'a');
|
||||
testOk('accessKey(a) + 0min', 'a');
|
||||
testOk('accessKey(a) -0h', 'a');
|
||||
testOk('accessKey(a)+100ms', 'a', 0, 0.1);
|
||||
testOk('accessKey(a)-0.1s', 'a', 0, -0.1);
|
||||
|
||||
// Id references are not allowed
|
||||
testNotOk('svg.accessKey(a)', 'a');
|
||||
testNotOk('window.accessKey(a)', 'a');
|
||||
|
||||
// Case sensitivity
|
||||
testOk('accessKey(A)', 'A');
|
||||
testNotOk('accessKey(a)', 'A');
|
||||
testNotOk('accessKey(A)', 'a');
|
||||
|
||||
// Test unusual characters
|
||||
testOk('accessKey(-)', '-');
|
||||
testOk('accessKey(\\)', '\\');
|
||||
testOk('accessKey( )', ' ');
|
||||
testOk('accessKey(\x0D)', 0, KeyboardEvent.DOM_VK_RETURN);
|
||||
testOk('accessKey(\n)', 0, KeyboardEvent.DOM_VK_RETURN); // New line
|
||||
testOk('accessKey(\r)', 0, KeyboardEvent.DOM_VK_RETURN); // Carriage return
|
||||
testOk('accessKey(\x08)', 0, KeyboardEvent.DOM_VK_BACK_SPACE);
|
||||
testOk('accessKey(\x1B)', 0, KeyboardEvent.DOM_VK_ESCAPE);
|
||||
testOk('accessKey(\x7F)', 0, KeyboardEvent.DOM_VK_DELETE);
|
||||
|
||||
// Check some disallowed keys
|
||||
// -- For now we don't allow tab since the interaction with focus causes
|
||||
// confusing results
|
||||
testNotOk('accessKey(\x09)', 0, 9); // Tab
|
||||
|
||||
// Test setting the keyCode field
|
||||
testNotOk('accessKey(a)', 0, 97);
|
||||
testOk('accessKey(a)', 97, 66); // Give priority to charCode field
|
||||
testNotOk('accessKey(a)', 98, 97); // Give priority to charCode field
|
||||
|
||||
// Test unicode
|
||||
testOk("accessKey(\u20AC)", 8364); // euro-symbol
|
||||
|
||||
// Test an astral character just to make sure we don't crash
|
||||
testOk("accessKey(\uD835\uDC00)", 119808); // mathematical bold capital A
|
||||
// 0x1D400
|
||||
// Test bad surrogate pairs don't confuse us either
|
||||
testNotOk("accessKey(\uD800\uD800)", 97);
|
||||
testNotOk("accessKey(\uD80020)", 97);
|
||||
testNotOk("accessKey(\uD800)", 97);
|
||||
|
||||
// Test modifiers
|
||||
// -- When matching on charCode ignore shift and alt
|
||||
testNotOk('accessKey(a)', 'a', 0, 0, { ctrl: true });
|
||||
testNotOk('accessKey(a)', 'a', 0, 0, { meta: true });
|
||||
testOk('accessKey(a)', 'a', 0, 0, { alt: true });
|
||||
testOk('accessKey(a)', 'a', 0, 0, { shift: true });
|
||||
testNotOk('accessKey(a)', 'a', 0, 0, { shift: true, ctrl: true });
|
||||
testNotOk('accessKey(a)', 'a', 0, 0, { alt: true, meta: true });
|
||||
// -- When matching on keyCode ignore all
|
||||
testNotOk('accessKey(\x0D)', 0, 13, 0, { ctrl: true });
|
||||
testNotOk('accessKey(\x0D)', 0, 13, 0, { meta: true });
|
||||
testNotOk('accessKey(\x0D)', 0, 13, 0, { alt: true });
|
||||
testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true });
|
||||
testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true, ctrl: true });
|
||||
|
||||
testOpenEnd();
|
||||
testPreventDefault();
|
||||
testDispatchToWindow();
|
||||
testAdoptNode();
|
||||
testFauxEvent();
|
||||
is(getStartTime('accesskey(a); 1s'), 1,
|
||||
'Start time for accesskey(a) followed by a literal time');
|
||||
is(getStartTime('3s; accessKey(a)'), 3,
|
||||
'Start time for accesskey(a) preceded by a literal time');
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function testOk(spec, charCode, keyCode, offset, modifiers)
|
||||
{
|
||||
if (typeof offset == 'undefined') offset = 0;
|
||||
var msg = "No interval created for '" + spec +
|
||||
"' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" +
|
||||
getModifiersDescr(modifiers);
|
||||
ok(test(spec, charCode, keyCode, offset, modifiers), msg);
|
||||
}
|
||||
|
||||
function testNotOk(spec, charCode, keyCode, offset, modifiers)
|
||||
{
|
||||
if (typeof offset == 'undefined') offset = 0;
|
||||
var msg = "Interval unexpectedly created for '" + spec +
|
||||
"' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" +
|
||||
getModifiersDescr(modifiers);
|
||||
ok(!test(spec, charCode, keyCode, offset, modifiers), msg);
|
||||
}
|
||||
|
||||
function getModifiersDescr(modifiers)
|
||||
{
|
||||
if (typeof modifiers != 'object')
|
||||
return '';
|
||||
var str = ' modifiers set:';
|
||||
for (var key in modifiers) {
|
||||
if (modifiers[key]) str += ' ' + key;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function test(spec, charCode, keyCode, offset, modifiers)
|
||||
{
|
||||
gSvg.setCurrentTime(1);
|
||||
ok(gSvg.animationsPaused(), "Expected animations to be paused");
|
||||
|
||||
var anim = createAnim(spec);
|
||||
var evt = createEvent(charCode, keyCode, modifiers);
|
||||
|
||||
document.getElementById('circle').dispatchEvent(evt);
|
||||
|
||||
var gotStartTimeOk = true;
|
||||
try {
|
||||
var start = anim.getStartTime();
|
||||
if (offset) {
|
||||
var expected = gSvg.getCurrentTime() + offset;
|
||||
ok(Math.abs(expected - start) <= 0.00001,
|
||||
"Unexpected start time for animation with begin: " + spec +
|
||||
" got " + start + ", expected " + expected);
|
||||
} else {
|
||||
is(start, gSvg.getCurrentTime() + offset,
|
||||
"Unexpected start time for animation with begin: " + spec);
|
||||
}
|
||||
} catch(e) {
|
||||
is(e.name, "InvalidStateError",
|
||||
"Unexpected exception: " + e.name);
|
||||
is(e.code, DOMException.INVALID_STATE_ERR,
|
||||
"Unexpected exception code: " + e.code);
|
||||
gotStartTimeOk = false;
|
||||
}
|
||||
|
||||
anim.remove();
|
||||
|
||||
return gotStartTimeOk;
|
||||
}
|
||||
|
||||
function createAnim(beginSpec)
|
||||
{
|
||||
var anim = document.createElementNS(gSvgns, 'animate');
|
||||
function createAnim(beginSpec) {
|
||||
const anim = document.createElementNS(gSvgns, 'animate');
|
||||
anim.setAttribute('attributeName', 'cx');
|
||||
anim.setAttribute('values', '0; 100');
|
||||
anim.setAttribute('dur', '10s');
|
||||
|
@ -188,173 +44,34 @@ function createAnim(beginSpec)
|
|||
return document.getElementById('circle').appendChild(anim);
|
||||
}
|
||||
|
||||
function createEvent(charCode, keyCode, modifiers)
|
||||
{
|
||||
if (typeof charCode == 'string') {
|
||||
is(charCode.length, 1,
|
||||
"If charCode is a string it should be 1 character long");
|
||||
charCode = charCode.charCodeAt(0);
|
||||
} else if (typeof charCode == 'undefined') {
|
||||
charCode = 0;
|
||||
}
|
||||
args = { ctrl: false, alt: false, shift: false, meta: false };
|
||||
if (typeof modifiers == 'object') {
|
||||
for (var key in modifiers)
|
||||
args[key] = modifiers[key];
|
||||
}
|
||||
if (typeof keyCode == 'undefined') keyCode = 0;
|
||||
var evt = document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent("keypress", true, true, window,
|
||||
args['ctrl'],
|
||||
args['alt'],
|
||||
args['shift'],
|
||||
args['meta'],
|
||||
keyCode,
|
||||
charCode);
|
||||
return evt;
|
||||
}
|
||||
|
||||
function testOpenEnd()
|
||||
{
|
||||
// Test that an end specification with an accesskey value is treated as open
|
||||
// ended
|
||||
gSvg.setCurrentTime(0);
|
||||
ok(gSvg.animationsPaused(), "Expected animations to be paused");
|
||||
|
||||
var anim = createAnim('0s; 2s');
|
||||
anim.setAttribute('end', '1s; accessKey(a)');
|
||||
|
||||
gSvg.setCurrentTime(2);
|
||||
function testBeginValueIsNotSupported(beginSpec) {
|
||||
const anim = createAnim(beginSpec);
|
||||
|
||||
try {
|
||||
is(anim.getStartTime(), 2,
|
||||
"Unexpected start time for second interval of open-ended animation");
|
||||
anim.getStartTime();
|
||||
ok(false,
|
||||
`Should have failed to get start time for begin value: ${beginSpec}`);
|
||||
} catch(e) {
|
||||
is(e.name, "InvalidStateError",
|
||||
"Unexpected exception:" + e.name);
|
||||
is(e.name, 'InvalidStateError', `Unexpected exception: ${e.name}`);
|
||||
is(e.code, DOMException.INVALID_STATE_ERR,
|
||||
"Unexpected exception code:" + e.code);
|
||||
ok(false, "Failed to recognise accessKey as qualifying for creating an " +
|
||||
"open-ended interval");
|
||||
`Unexpected exception code: ${e.code}`);
|
||||
}
|
||||
|
||||
anim.remove();
|
||||
}
|
||||
|
||||
function testPreventDefault()
|
||||
{
|
||||
// SVG/SMIL don't specify what should happen if preventDefault is called on
|
||||
// the keypress event. For now, for consistency with event timing we ignore
|
||||
// it.
|
||||
gSvg.setCurrentTime(1);
|
||||
ok(gSvg.animationsPaused(), "Expected animations to be paused");
|
||||
|
||||
var anim = createAnim('accessKey(a)');
|
||||
var evt = createEvent('a');
|
||||
|
||||
var circle = document.getElementById('circle');
|
||||
var func = function(evt) { evt.preventDefault(); }
|
||||
circle.addEventListener('keypress', func);
|
||||
circle.dispatchEvent(evt);
|
||||
|
||||
function getStartTime(beginSpec) {
|
||||
const anim = createAnim(beginSpec);
|
||||
let startTime;
|
||||
try {
|
||||
var start = anim.getStartTime();
|
||||
} catch(e) {
|
||||
ok(false, "preventDefault() cancelled accessKey handling");
|
||||
}
|
||||
|
||||
circle.removeEventListener('keypress', func);
|
||||
startTime = anim.getStartTime();
|
||||
} catch (e) { }
|
||||
anim.remove();
|
||||
|
||||
return startTime;
|
||||
}
|
||||
|
||||
function testDispatchToWindow()
|
||||
{
|
||||
gSvg.setCurrentTime(1);
|
||||
ok(gSvg.animationsPaused(), "Expected animations to be paused");
|
||||
|
||||
var anim = createAnim('accessKey(a)');
|
||||
var evt = createEvent('a');
|
||||
|
||||
window.dispatchEvent(evt);
|
||||
|
||||
try {
|
||||
var start = anim.getStartTime();
|
||||
} catch(e) {
|
||||
ok(false, "Key event dispatched to the window failed to trigger " +
|
||||
"accesskey handling");
|
||||
}
|
||||
|
||||
anim.remove();
|
||||
}
|
||||
|
||||
function testAdoptNode()
|
||||
{
|
||||
gSvg.setCurrentTime(1);
|
||||
ok(gSvg.animationsPaused(), "Expected animations to be paused");
|
||||
|
||||
// Create a new document with an animation element
|
||||
var newdoc = document.implementation.createDocument(gSvgns, 'svg', null);
|
||||
var anim = newdoc.createElementNS(gSvgns, 'animate');
|
||||
anim.setAttribute('attributeName', 'cx');
|
||||
anim.setAttribute('values', '0; 100');
|
||||
anim.setAttribute('dur', '10s');
|
||||
anim.setAttribute('begin', 'accesskey(a)');
|
||||
newdoc.documentElement.appendChild(anim);
|
||||
|
||||
// Adopt
|
||||
ok(anim.ownerDocument !== document,
|
||||
"Expected newly created animation to belong to a different doc");
|
||||
document.adoptNode(anim);
|
||||
document.getElementById('circle').appendChild(anim);
|
||||
ok(anim.ownerDocument === document,
|
||||
"Expected newly created animation to belong to the same doc");
|
||||
|
||||
var evt = createEvent('a');
|
||||
|
||||
// Now fire an event at the original window and check nothing happens
|
||||
newdoc.dispatchEvent(evt);
|
||||
try {
|
||||
var start = anim.getStartTime();
|
||||
ok(false, "Adopted node still receiving accesskey events from old doc");
|
||||
} catch(e) {
|
||||
// Ok
|
||||
}
|
||||
|
||||
// And then fire at our window
|
||||
document.dispatchEvent(evt);
|
||||
try {
|
||||
var start = anim.getStartTime();
|
||||
} catch(e) {
|
||||
ok(false, "Adopted node failed to catch accesskey event");
|
||||
}
|
||||
|
||||
anim.remove();
|
||||
}
|
||||
|
||||
function testFauxEvent()
|
||||
{
|
||||
// Test a non-KeyEvent labelled as a key event
|
||||
gSvg.setCurrentTime(0);
|
||||
ok(gSvg.animationsPaused(), "Expected animations to be paused");
|
||||
|
||||
var anim = createAnim('accessKey(a)');
|
||||
var evt = document.createEvent("SVGEvents");
|
||||
evt.initEvent("keypress", true, true);
|
||||
document.getElementById('circle').dispatchEvent(evt);
|
||||
|
||||
// We're really just testing that the above didn't crash us, but while we're
|
||||
// at it, just do a sanity check that we didn't also create an interval
|
||||
try {
|
||||
var start = anim.getStartTime();
|
||||
ok(false, "Faux event generated interval");
|
||||
} catch(e) {
|
||||
// All is well
|
||||
}
|
||||
|
||||
anim.remove();
|
||||
}
|
||||
|
||||
window.addEventListener("load", main);
|
||||
window.addEventListener('load', main);
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="
|
||||
document.documentElement.pauseAnimations();
|
||||
document.documentElement.setCurrentTime(0);
|
||||
keypress(0x20);
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green" begin="accesskey( )" dur="4s"/>
|
||||
<set attributeName="width" attributeType="XML"
|
||||
to="200" begin="accesskey(!)" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 647 B |
|
@ -1,15 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="
|
||||
document.documentElement.pauseAnimations();
|
||||
document.documentElement.setCurrentTime(0);
|
||||
keypress(0x0D);
|
||||
delayedSnapshot(2)">
|
||||
<script xlink:href="event-util.js" type="text/javascript"/>
|
||||
<circle id="circle" r="10"/>
|
||||
<rect width="100" height="100" fill="red">
|
||||
<set attributeName="fill" attributeType="CSS"
|
||||
to="green" begin="accesskey(
)" dur="4s"/>
|
||||
</rect>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 544 B |
|
@ -22,16 +22,3 @@ function click(targetId)
|
|||
var target = document.getElementById(targetId);
|
||||
target.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
function keypress(charCode)
|
||||
{
|
||||
var evt = document.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent("keypress", true, true, window,
|
||||
false, // ctrlKeyArg
|
||||
false, // altKeyArg
|
||||
false, // shiftKeyArg
|
||||
false, // metaKeyArg
|
||||
0, // keyCode
|
||||
charCode);
|
||||
document.documentElement.dispatchEvent(evt);
|
||||
}
|
||||
|
|
|
@ -28,5 +28,3 @@ random-if(Android) == event-begin-timeevent-3.svg green-box-ref.svg
|
|||
== event-target-surgery-2.svg green-box-ref.svg
|
||||
== event-target-surgery-3.svg green-box-ref.svg
|
||||
== event-target-non-svg-1.xhtml green-box-ref.xhtml
|
||||
== accesskey-entity-1.svg green-box-ref.svg
|
||||
== accesskey-entity-2.svg green-box-ref.svg
|
||||
|
|
Загрузка…
Ссылка в новой задаче