[orca] Add support for aria-hidden="true" in Gecko content



commit 9c878ead3956f49d3fcedeb32063b91e171dcd71
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Mon Aug 25 05:54:13 2014 -0400

    Add support for aria-hidden="true" in Gecko content

 src/orca/script_utilities.py                       |   12 ++++-
 src/orca/scripts/toolkits/Gecko/script.py          |   17 ++++--
 .../scripts/toolkits/Gecko/script_utilities.py     |    6 ++
 src/orca/structural_navigation.py                  |    8 ++-
 .../firefox/flat_review_hidden_elements.params     |    1 +
 .../firefox/flat_review_hidden_elements.py         |   51 +++++++++++++++++++
 .../firefox/html_struct_nav_hidden_paragraphs.py   |   52 +++----------------
 .../keystrokes/firefox/line_nav_hidden_elements.py |   50 +++----------------
 .../firefox/say_all_hidden_elements.params         |    1 +
 test/keystrokes/firefox/say_all_hidden_elements.py |   21 ++++++++
 10 files changed, 123 insertions(+), 96 deletions(-)
---
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 5105e3b..c5c2663 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -771,10 +771,16 @@ class Utilities:
 
         return False
 
+    def isHidden(self, obj):
+        return False
+
     def isLayoutOnly(self, obj):
         """Returns True if the given object is a container which has
         no presentable information (label, name, displayed text, etc.)."""
 
+        if self.isHidden(obj):
+            return True
+
         layoutOnly = False
 
         try:
@@ -1172,11 +1178,13 @@ class Utilities:
                    and ci.getLayer() == pyatspi.LAYER_POPUP:
                     return child
 
-    @staticmethod
-    def pursueForFlatReview(obj):
+    def pursueForFlatReview(self, obj):
         """Determines if we should look any further at the object
         for flat review."""
 
+        if self.isHidden(obj):
+            return False
+
         try:
             state = obj.getState()
         except:
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 5fd6e0f..1b6b8a7 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -2162,8 +2162,10 @@ class Script(default.Script):
                                              pyatspi.ROLE_LIST_BOX,
                                              pyatspi.ROLE_LIST]
 
+        isHidden = self.utilities.isHidden(obj)
+
         text = self.utilities.queryNonEmptyText(obj)
-        if text:
+        if text and not isHidden:
             unicodeText = self.utilities.unicodeText(obj)
 
             # Delete the final space character if we find it.  Otherwise,
@@ -2195,7 +2197,7 @@ class Script(default.Script):
         # to place the caret inside the list, but rather treat the list
         # as a single object.  Otherwise, if it has children, look there.
         #
-        elif obj.childCount and obj[0] and not doNotDescend:
+        elif obj.childCount and obj[0] and not doNotDescend and not isHidden:
             try:
                 return self.findNextCaretInOrder(obj[0],
                                                  -1,
@@ -2203,7 +2205,7 @@ class Script(default.Script):
             except:
                 pass
 
-        elif includeNonText and (startOffset < 0):
+        elif includeNonText and startOffset < 0 and not isHidden:
             extents = obj.queryComponent().getExtents(0)
             if (extents.width != 0) and (extents.height != 0):
                 return [obj, 0]
@@ -2272,8 +2274,10 @@ class Script(default.Script):
                                              pyatspi.ROLE_LIST_BOX,
                                              pyatspi.ROLE_LIST]
 
+        isHidden = self.utilities.isHidden(obj)
+
         text = self.utilities.queryNonEmptyText(obj)
-        if text:
+        if text and not isHidden:
             unicodeText = self.utilities.unicodeText(obj)
 
             # Delete the final space character if we find it.  Otherwise,
@@ -2305,7 +2309,8 @@ class Script(default.Script):
         # to place the caret inside the list, but rather treat the list
         # as a single object.  Otherwise, if it has children, look there.
         #
-        elif obj.childCount and obj[obj.childCount - 1] and not doNotDescend:
+        elif obj.childCount and obj[obj.childCount - 1] and not doNotDescend \
+             and not isHidden:
             try:
                 return self.findPreviousCaretInOrder(
                     obj[obj.childCount - 1],
@@ -2314,7 +2319,7 @@ class Script(default.Script):
             except:
                 pass
 
-        elif includeNonText and (startOffset < 0):
+        elif includeNonText and startOffset < 0 and not isHidden:
             extents = obj.queryComponent().getExtents(0)
             if (extents.width != 0) and (extents.height != 0):
                 return [obj, 0]
diff --git a/src/orca/scripts/toolkits/Gecko/script_utilities.py 
b/src/orca/scripts/toolkits/Gecko/script_utilities.py
index b17698f..843237c 100644
--- a/src/orca/scripts/toolkits/Gecko/script_utilities.py
+++ b/src/orca/scripts/toolkits/Gecko/script_utilities.py
@@ -264,6 +264,12 @@ class Utilities(script_utilities.Utilities):
 
         return obj and obj.getRole() == pyatspi.ROLE_PASSWORD_TEXT
 
+    def isHidden(self, obj):
+        attrs = dict([attr.split(':', 1) for attr in obj.getAttributes()])
+        isHidden = attrs.get('hidden', False)
+
+        return isHidden
+
     def isReadOnlyTextArea(self, obj):
         """Returns True if obj is a text entry area that is read only."""
 
diff --git a/src/orca/structural_navigation.py b/src/orca/structural_navigation.py
index 230eac0..3f00972 100644
--- a/src/orca/structural_navigation.py
+++ b/src/orca/structural_navigation.py
@@ -813,6 +813,7 @@ class StructuralNavigation:
         col.freeMatchRule(rule)
         if criteria.applyPredicate:
             rv = list(filter(structuralNavigationObject.predicate, rv))
+        rv = list(filter(lambda x: not self._script.utilities.isHidden(x), rv))
 
         return rv
 
@@ -1011,6 +1012,7 @@ class StructuralNavigation:
                         True)
                     wrapped = True
                     if len(results) > 0 \
+                       and not self._script.utilities.isHidden(results[0]) \
                        and (not predicate or predicate(results[0])):
                         match = results[0]
                     else:
@@ -1024,7 +1026,8 @@ class StructuralNavigation:
                             True)
             elif len(results) > 0:
                 if results[0] in ancestors \
-                   or predicate and not predicate(results[0]):
+                   or self._script.utilities.isHidden(results[0]) \
+                   or (predicate and not predicate(results[0])):
                     results = collection.getMatchesTo(\
                         results[0],
                         matchRule,
@@ -1075,7 +1078,8 @@ class StructuralNavigation:
                 True)
             if len(results) > 0 and not results[0] in ancestors:
                 currentObj = results[0]
-                if not predicate or predicate(currentObj):
+                if not self._script.utilities.isHidden(currentObj) \
+                   and (not predicate or predicate(currentObj)):
                     match = currentObj
             elif wrap and not wrapped:
                 wrapped = True
diff --git a/test/keystrokes/firefox/flat_review_hidden_elements.params 
b/test/keystrokes/firefox/flat_review_hidden_elements.params
new file mode 100644
index 0000000..cf441c9
--- /dev/null
+++ b/test/keystrokes/firefox/flat_review_hidden_elements.params
@@ -0,0 +1 @@
+PARAMS=$TEST_DIR/../../html/hidden.html
diff --git a/test/keystrokes/firefox/flat_review_hidden_elements.py 
b/test/keystrokes/firefox/flat_review_hidden_elements.py
new file mode 100644
index 0000000..44bd651
--- /dev/null
+++ b/test/keystrokes/firefox/flat_review_hidden_elements.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+
+"""Test of flat review in content with hidden elements."""
+
+from macaroon.playback import *
+import utils
+
+sequence = MacroSequence()
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("KP_8"))
+sequence.append(utils.AssertPresentationAction(
+    "1. Flat review current line",
+    ["BRAILLE LINE:  'This element is not hidden. $l'",
+     "     VISIBLE:  'This element is not hidden. $l', cursor=1",
+     "SPEECH OUTPUT: 'This element is not hidden.'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("KP_9"))
+sequence.append(utils.AssertPresentationAction(
+    "2. Flat review next line",
+    ["BRAILLE LINE:  'This element is in a parent which is not hidden. $l'",
+     "     VISIBLE:  'This element is in a parent whic', cursor=1",
+     "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("KP_9"))
+sequence.append(utils.AssertPresentationAction(
+    "3. Flat review next line",
+    ["BRAILLE LINE:  'This element is not hidden. $l'",
+     "     VISIBLE:  'This element is not hidden. $l', cursor=1",
+     "SPEECH OUTPUT: 'This element is not hidden.'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("KP_7"))
+sequence.append(utils.AssertPresentationAction(
+    "4. Flat review previous line",
+    ["BRAILLE LINE:  'This element is in a parent which is not hidden. $l'",
+     "     VISIBLE:  'This element is in a parent whic', cursor=1",
+     "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("KP_7"))
+sequence.append(utils.AssertPresentationAction(
+    "5. Flat review previous line",
+    ["BRAILLE LINE:  'This element is not hidden. $l'",
+     "     VISIBLE:  'This element is not hidden. $l', cursor=1",
+     "SPEECH OUTPUT: 'This element is not hidden.'"]))
+
+sequence.append(utils.AssertionSummaryAction())
+sequence.start()
diff --git a/test/keystrokes/firefox/html_struct_nav_hidden_paragraphs.py 
b/test/keystrokes/firefox/html_struct_nav_hidden_paragraphs.py
index 0bdd17c..54d6a14 100644
--- a/test/keystrokes/firefox/html_struct_nav_hidden_paragraphs.py
+++ b/test/keystrokes/firefox/html_struct_nav_hidden_paragraphs.py
@@ -19,15 +19,6 @@ sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("p"))
 sequence.append(utils.AssertPresentationAction(
     "2. p to next paragraph",
-    ["KNOWN ISSUE: Orca should not present this",
-     "BRAILLE LINE:  'This element hidden by ARIA.'",
-     "     VISIBLE:  'This element hidden by ARIA.', cursor=1",
-     "SPEECH OUTPUT: 'This element hidden by ARIA.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("p"))
-sequence.append(utils.AssertPresentationAction(
-    "3. p to next paragraph",
     ["BRAILLE LINE:  'This element hidden by position off screen.'",
      "     VISIBLE:  'This element hidden by position ', cursor=1",
      "SPEECH OUTPUT: 'This element hidden by position off screen.'"]))
@@ -35,7 +26,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("p"))
 sequence.append(utils.AssertPresentationAction(
-    "4. p to next paragraph",
+    "3. p to next paragraph",
     ["BRAILLE LINE:  'This element is in a parent which is not hidden.'",
      "     VISIBLE:  'This element is in a parent whic', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'"]))
@@ -43,8 +34,8 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("p"))
 sequence.append(utils.AssertPresentationAction(
-    "5. p to next paragraph",
-    ["KNOWN ISSUE: Orca should not present this",
+    "4. p to next paragraph",
+    ["KNOWN ISSUE: https://bugzilla.mozilla.org/show_bug.cgi?id=974238";,
      "BRAILLE LINE:  'This element is in a parent hidden by ARIA.'",
      "     VISIBLE:  'This element is in a parent hidd', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent hidden by ARIA.'"]))
@@ -52,23 +43,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("p"))
 sequence.append(utils.AssertPresentationAction(
-    "6. p to next paragraph",
-    ["BRAILLE LINE:  'This element is in a parent hidden by position off screen'",
-     "     VISIBLE:  'This element is in a parent hidd', cursor=1",
-     "SPEECH OUTPUT: 'This element is in a parent hidden by position off screen'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("p"))
-sequence.append(utils.AssertPresentationAction(
-    "7. p to next paragraph",
-    ["BRAILLE LINE:  'This element is not hidden.'",
-     "     VISIBLE:  'This element is not hidden.', cursor=1",
-     "SPEECH OUTPUT: 'This element is not hidden.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("<Shift>p"))
-sequence.append(utils.AssertPresentationAction(
-    "8. Shift p to previous paragraph",
+    "5. p to next paragraph",
     ["BRAILLE LINE:  'This element is in a parent hidden by position off screen'",
      "     VISIBLE:  'This element is in a parent hidd', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent hidden by position off screen'"]))
@@ -76,8 +51,8 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("<Shift>p"))
 sequence.append(utils.AssertPresentationAction(
-    "9. Shift p to previous paragraph",
-    ["KNOWN ISSUE: Orca should not present this",
+    "6. Shift p to previous paragraph",
+    ["KNOWN ISSUE: https://bugzilla.mozilla.org/show_bug.cgi?id=974238";,
      "BRAILLE LINE:  'This element is in a parent hidden by ARIA.'",
      "     VISIBLE:  'This element is in a parent hidd', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent hidden by ARIA.'"]))
@@ -85,7 +60,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("<Shift>p"))
 sequence.append(utils.AssertPresentationAction(
-    "10. Shift p to previous paragraph",
+    "7. Shift p to previous paragraph",
     ["BRAILLE LINE:  'This element is in a parent which is not hidden.'",
      "     VISIBLE:  'This element is in a parent whic', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'"]))
@@ -93,7 +68,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("<Shift>p"))
 sequence.append(utils.AssertPresentationAction(
-    "11. Shift p to previous paragraph",
+    "8. Shift p to previous paragraph",
     ["BRAILLE LINE:  'This element hidden by position off screen.'",
      "     VISIBLE:  'This element hidden by position ', cursor=1",
      "SPEECH OUTPUT: 'This element hidden by position off screen.'"]))
@@ -101,16 +76,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("<Shift>p"))
 sequence.append(utils.AssertPresentationAction(
-    "12. Shift p to previous paragraph",
-    ["KNOWN ISSUE: Orca should not present this",
-     "BRAILLE LINE:  'This element hidden by ARIA.'",
-     "     VISIBLE:  'This element hidden by ARIA.', cursor=1",
-     "SPEECH OUTPUT: 'This element hidden by ARIA.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("<Shift>p"))
-sequence.append(utils.AssertPresentationAction(
-    "13. Shift p to previous paragraph",
+    "9. Shift p to previous paragraph",
     ["BRAILLE LINE:  'This element is not hidden.'",
      "     VISIBLE:  'This element is not hidden.', cursor=1",
      "SPEECH OUTPUT: 'This element is not hidden.'"]))
diff --git a/test/keystrokes/firefox/line_nav_hidden_elements.py 
b/test/keystrokes/firefox/line_nav_hidden_elements.py
index cc9e086..0d25900 100644
--- a/test/keystrokes/firefox/line_nav_hidden_elements.py
+++ b/test/keystrokes/firefox/line_nav_hidden_elements.py
@@ -19,15 +19,6 @@ sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
     "2. Line Down",
-    ["KNOWN ISSUE: Orca should not present this",
-     "BRAILLE LINE:  'This element hidden by ARIA.'",
-     "     VISIBLE:  'This element hidden by ARIA.', cursor=1",
-     "SPEECH OUTPUT: 'This element hidden by ARIA.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("Down"))
-sequence.append(utils.AssertPresentationAction(
-    "3. Line Down",
     ["BRAILLE LINE:  'This element hidden by position off screen.'",
      "     VISIBLE:  'This element hidden by position ', cursor=1",
      "SPEECH OUTPUT: 'This element hidden by position off screen.'"]))
@@ -35,7 +26,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
-    "4. Line Down",
+    "3. Line Down",
     ["BRAILLE LINE:  'This element is in a parent which is not hidden.'",
      "     VISIBLE:  'This element is in a parent whic', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'"]))
@@ -43,16 +34,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
-    "5. Line Down",
-    ["KNOWN ISSUE: Orca should not present this",
-     "BRAILLE LINE:  'This element is in a parent hidden by ARIA.'",
-     "     VISIBLE:  'This element is in a parent hidd', cursor=1",
-     "SPEECH OUTPUT: 'This element is in a parent hidden by ARIA.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("Down"))
-sequence.append(utils.AssertPresentationAction(
-    "6. Line Down",
+    "4. Line Down",
     ["BRAILLE LINE:  'This element is in a parent hidden by position off screen'",
      "     VISIBLE:  'This element is in a parent hidd', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent hidden by position off screen'"]))
@@ -60,7 +42,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Down"))
 sequence.append(utils.AssertPresentationAction(
-    "7. Line Down",
+    "5. Line Down",
     ["BRAILLE LINE:  'This element is not hidden.'",
      "     VISIBLE:  'This element is not hidden.', cursor=1",
      "SPEECH OUTPUT: 'This element is not hidden.'"]))
@@ -68,7 +50,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
-    "8. Line Up",
+    "6. Line Up",
     ["BRAILLE LINE:  'This element is in a parent hidden by position off screen'",
      "     VISIBLE:  'This element is in a parent hidd', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent hidden by position off screen'"]))
@@ -76,16 +58,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
-    "9. Line Up",
-    ["KNOWN ISSUE: Orca should not present this",
-     "BRAILLE LINE:  'This element is in a parent hidden by ARIA.'",
-     "     VISIBLE:  'This element is in a parent hidd', cursor=1",
-     "SPEECH OUTPUT: 'This element is in a parent hidden by ARIA.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("Up"))
-sequence.append(utils.AssertPresentationAction(
-    "10. Line Up",
+    "7. Line Up",
     ["BRAILLE LINE:  'This element is in a parent which is not hidden.'",
      "     VISIBLE:  'This element is in a parent whic', cursor=1",
      "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'"]))
@@ -93,7 +66,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
-    "11. Line Up",
+    "8. Line Up",
     ["BRAILLE LINE:  'This element hidden by position off screen.'",
      "     VISIBLE:  'This element hidden by position ', cursor=1",
      "SPEECH OUTPUT: 'This element hidden by position off screen.'"]))
@@ -101,16 +74,7 @@ sequence.append(utils.AssertPresentationAction(
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Up"))
 sequence.append(utils.AssertPresentationAction(
-    "12. Line Up",
-    ["KNOWN ISSUE: Orca should not present this",
-     "BRAILLE LINE:  'This element hidden by ARIA.'",
-     "     VISIBLE:  'This element hidden by ARIA.', cursor=1",
-     "SPEECH OUTPUT: 'This element hidden by ARIA.'"]))
-
-sequence.append(utils.StartRecordingAction())
-sequence.append(KeyComboAction("Up"))
-sequence.append(utils.AssertPresentationAction(
-    "13. Line Up",
+    "9. Line Up",
     ["BRAILLE LINE:  'This element is not hidden.'",
      "     VISIBLE:  'This element is not hidden.', cursor=1",
      "SPEECH OUTPUT: 'This element is not hidden.'"]))
diff --git a/test/keystrokes/firefox/say_all_hidden_elements.params 
b/test/keystrokes/firefox/say_all_hidden_elements.params
new file mode 100644
index 0000000..cf441c9
--- /dev/null
+++ b/test/keystrokes/firefox/say_all_hidden_elements.params
@@ -0,0 +1 @@
+PARAMS=$TEST_DIR/../../html/hidden.html
diff --git a/test/keystrokes/firefox/say_all_hidden_elements.py 
b/test/keystrokes/firefox/say_all_hidden_elements.py
new file mode 100644
index 0000000..25f2247
--- /dev/null
+++ b/test/keystrokes/firefox/say_all_hidden_elements.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+"""Test of sayAll."""
+
+from macaroon.playback import *
+import utils
+
+sequence = MacroSequence()
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("KP_Add"))
+sequence.append(utils.AssertPresentationAction(
+    "1. KP_Add to do a SayAll",
+    ["SPEECH OUTPUT: 'This element is not hidden.'",
+     "SPEECH OUTPUT: 'This element hidden by position off screen.'",
+     "SPEECH OUTPUT: 'This element is in a parent which is not hidden.'",
+     "SPEECH OUTPUT: 'This element is in a parent hidden by position off screen'",
+     "SPEECH OUTPUT: 'This element is not hidden.'"]))
+
+sequence.append(utils.AssertionSummaryAction())
+sequence.start()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]