зеркало из https://github.com/mozilla/gecko-dev.git
Merging backout
This commit is contained in:
Коммит
4fd12ef2e8
|
@ -81,7 +81,6 @@ CPPSRCS = \
|
||||||
nsAccessibilityAtoms.cpp \
|
nsAccessibilityAtoms.cpp \
|
||||||
nsCoreUtils.cpp \
|
nsCoreUtils.cpp \
|
||||||
nsAccUtils.cpp \
|
nsAccUtils.cpp \
|
||||||
nsNameUtils.cpp \
|
|
||||||
nsRelUtils.cpp \
|
nsRelUtils.cpp \
|
||||||
nsAccessibilityService.cpp \
|
nsAccessibilityService.cpp \
|
||||||
nsAccessible.cpp \
|
nsAccessible.cpp \
|
||||||
|
@ -93,6 +92,7 @@ CPPSRCS = \
|
||||||
nsApplicationAccessible.cpp \
|
nsApplicationAccessible.cpp \
|
||||||
nsCaretAccessible.cpp \
|
nsCaretAccessible.cpp \
|
||||||
nsTextAccessible.cpp \
|
nsTextAccessible.cpp \
|
||||||
|
nsTextEquivUtils.cpp \
|
||||||
nsTextAttrs.cpp \
|
nsTextAttrs.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_ALERT,
|
nsIAccessibleRole::ROLE_ALERT,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -73,6 +74,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_DIALOG,
|
nsIAccessibleRole::ROLE_DIALOG,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -81,6 +83,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_APPLICATION,
|
nsIAccessibleRole::ROLE_APPLICATION,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -89,6 +92,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_DOCUMENT,
|
nsIAccessibleRole::ROLE_DOCUMENT,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_READONLY,
|
nsIAccessibleStates::STATE_READONLY,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -97,6 +101,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_PUSHBUTTON,
|
nsIAccessibleRole::ROLE_PUSHBUTTON,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eClickAction,
|
eClickAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED},
|
{&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED},
|
||||||
{&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED},
|
{&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED},
|
||||||
|
@ -107,6 +112,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_CHECKBUTTON,
|
nsIAccessibleRole::ROLE_CHECKBUTTON,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eCheckUncheckAction,
|
eCheckUncheckAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_CHECKABLE,
|
nsIAccessibleStates::STATE_CHECKABLE,
|
||||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
|
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
|
||||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
|
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
|
||||||
|
@ -118,6 +124,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_COLUMNHEADER,
|
nsIAccessibleRole::ROLE_COLUMNHEADER,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
|
@ -129,6 +136,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_COMBOBOX,
|
nsIAccessibleRole::ROLE_COMBOBOX,
|
||||||
eHasValueMinMax,
|
eHasValueMinMax,
|
||||||
eOpenCloseAction,
|
eOpenCloseAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
|
nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
|
||||||
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
|
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
|
@ -139,6 +147,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_DIALOG,
|
nsIAccessibleRole::ROLE_DIALOG,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -147,6 +156,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_DOCUMENT,
|
nsIAccessibleRole::ROLE_DOCUMENT,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_READONLY,
|
nsIAccessibleStates::STATE_READONLY,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -155,6 +165,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_TABLE,
|
nsIAccessibleRole::ROLE_TABLE,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_FOCUSABLE,
|
nsIAccessibleStates::STATE_FOCUSABLE,
|
||||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
|
@ -165,6 +176,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_GRID_CELL,
|
nsIAccessibleRole::ROLE_GRID_CELL,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
|
@ -176,6 +188,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_GROUPING,
|
nsIAccessibleRole::ROLE_GROUPING,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -184,6 +197,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_HEADING,
|
nsIAccessibleRole::ROLE_HEADING,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -192,6 +206,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_GRAPHIC,
|
nsIAccessibleRole::ROLE_GRAPHIC,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -200,6 +215,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_LABEL,
|
nsIAccessibleRole::ROLE_LABEL,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -208,6 +224,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_LINK,
|
nsIAccessibleRole::ROLE_LINK,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eJumpAction,
|
eJumpAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_LINKED,
|
nsIAccessibleStates::STATE_LINKED,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -216,6 +233,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_LIST,
|
nsIAccessibleRole::ROLE_LIST,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_READONLY,
|
nsIAccessibleStates::STATE_READONLY,
|
||||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
||||||
kEndEntry
|
kEndEntry
|
||||||
|
@ -225,6 +243,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_LISTBOX,
|
nsIAccessibleRole::ROLE_LISTBOX,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
||||||
|
@ -235,6 +254,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_LISTITEM,
|
nsIAccessibleRole::ROLE_LISTITEM,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction, // XXX: should depend on state, parent accessible
|
eNoAction, // XXX: should depend on state, parent accessible
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_READONLY,
|
nsIAccessibleStates::STATE_READONLY,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
|
@ -243,11 +263,30 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
|
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"log",
|
||||||
|
nsIAccessibleRole::ROLE_NOTHING,
|
||||||
|
eNoValue,
|
||||||
|
eNoAction,
|
||||||
|
ePoliteLiveAttr,
|
||||||
|
kNoReqStates,
|
||||||
|
kEndEntry
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marquee",
|
||||||
|
nsIAccessibleRole::ROLE_NOTHING,
|
||||||
|
eNoValue,
|
||||||
|
eNoAction,
|
||||||
|
eOffLiveAttr,
|
||||||
|
kNoReqStates,
|
||||||
|
kEndEntry
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"math",
|
"math",
|
||||||
nsIAccessibleRole::ROLE_FLAT_EQUATION,
|
nsIAccessibleRole::ROLE_FLAT_EQUATION,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -257,6 +296,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction, // XXX: technically accessibles of menupopup role haven't
|
eNoAction, // XXX: technically accessibles of menupopup role haven't
|
||||||
// any action, but menu can be open or close.
|
// any action, but menu can be open or close.
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -265,6 +305,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_MENUBAR,
|
nsIAccessibleRole::ROLE_MENUBAR,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -273,6 +314,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_MENUITEM,
|
nsIAccessibleRole::ROLE_MENUITEM,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eClickAction,
|
eClickAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||||
|
@ -284,6 +326,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_CHECK_MENU_ITEM,
|
nsIAccessibleRole::ROLE_CHECK_MENU_ITEM,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eClickAction,
|
eClickAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_CHECKABLE,
|
nsIAccessibleStates::STATE_CHECKABLE,
|
||||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
|
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
|
||||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
|
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
|
||||||
|
@ -294,6 +337,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_RADIO_MENU_ITEM,
|
nsIAccessibleRole::ROLE_RADIO_MENU_ITEM,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eClickAction,
|
eClickAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_CHECKABLE,
|
nsIAccessibleStates::STATE_CHECKABLE,
|
||||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
|
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
|
||||||
kEndEntry
|
kEndEntry
|
||||||
|
@ -303,6 +347,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_OPTION,
|
nsIAccessibleRole::ROLE_OPTION,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eSelectAction,
|
eSelectAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
|
@ -316,6 +361,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_NOTHING,
|
nsIAccessibleRole::ROLE_NOTHING,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -324,6 +370,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_PROGRESSBAR,
|
nsIAccessibleRole::ROLE_PROGRESSBAR,
|
||||||
eHasValueMinMax,
|
eHasValueMinMax,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
nsIAccessibleStates::STATE_READONLY,
|
nsIAccessibleStates::STATE_READONLY,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -332,6 +379,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_RADIOBUTTON,
|
nsIAccessibleRole::ROLE_RADIOBUTTON,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eSelectAction,
|
eSelectAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
|
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
|
||||||
kEndEntry
|
kEndEntry
|
||||||
|
@ -341,6 +389,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_GROUPING,
|
nsIAccessibleRole::ROLE_GROUPING,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -349,6 +398,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_PANE,
|
nsIAccessibleRole::ROLE_PANE,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -357,6 +407,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_ROW,
|
nsIAccessibleRole::ROLE_ROW,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
|
@ -367,6 +418,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_ROWHEADER,
|
nsIAccessibleRole::ROLE_ROWHEADER,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
|
@ -378,6 +430,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_SECTION,
|
nsIAccessibleRole::ROLE_SECTION,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -386,6 +439,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_SEPARATOR,
|
nsIAccessibleRole::ROLE_SEPARATOR,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -394,6 +448,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_SLIDER,
|
nsIAccessibleRole::ROLE_SLIDER,
|
||||||
eHasValueMinMax,
|
eHasValueMinMax,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
kEndEntry
|
kEndEntry
|
||||||
|
@ -403,6 +458,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_SPINBUTTON,
|
nsIAccessibleRole::ROLE_SPINBUTTON,
|
||||||
eHasValueMinMax,
|
eHasValueMinMax,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
kEndEntry
|
kEndEntry
|
||||||
|
@ -412,6 +468,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_STATUSBAR,
|
nsIAccessibleRole::ROLE_STATUSBAR,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
ePoliteLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -420,6 +477,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_PAGETAB,
|
nsIAccessibleRole::ROLE_PAGETAB,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eSwitchAction,
|
eSwitchAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -428,6 +486,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_PAGETABLIST,
|
nsIAccessibleRole::ROLE_PAGETABLIST,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
ePoliteLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -436,6 +495,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_PROPERTYPAGE,
|
nsIAccessibleRole::ROLE_PROPERTYPAGE,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -444,6 +504,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_ENTRY,
|
nsIAccessibleRole::ROLE_ENTRY,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eActivateAction,
|
eActivateAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
// Manually map EXT_STATE_SINGLE_LINE and EXT_STATE_MULTI_LINE FROM aria-multiline
|
// Manually map EXT_STATE_SINGLE_LINE and EXT_STATE_MULTI_LINE FROM aria-multiline
|
||||||
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
|
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
|
||||||
|
@ -452,11 +513,21 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"timer",
|
||||||
|
nsIAccessibleRole::ROLE_NOTHING,
|
||||||
|
eNoValue,
|
||||||
|
eNoAction,
|
||||||
|
eOffLiveAttr,
|
||||||
|
kNoReqStates,
|
||||||
|
kEndEntry
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"toolbar",
|
"toolbar",
|
||||||
nsIAccessibleRole::ROLE_TOOLBAR,
|
nsIAccessibleRole::ROLE_TOOLBAR,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -465,6 +536,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_TOOLTIP,
|
nsIAccessibleRole::ROLE_TOOLTIP,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
},
|
},
|
||||||
|
@ -473,6 +545,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_OUTLINE,
|
nsIAccessibleRole::ROLE_OUTLINE,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
||||||
|
@ -483,6 +556,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
nsIAccessibleRole::ROLE_TREE_TABLE,
|
nsIAccessibleRole::ROLE_TREE_TABLE,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
|
||||||
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
|
||||||
|
@ -494,13 +568,15 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eActivateAction, // XXX: should expose second 'expand/collapse' action based
|
eActivateAction, // XXX: should expose second 'expand/collapse' action based
|
||||||
// on states
|
// on states
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
|
||||||
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||||
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
|
||||||
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
|
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
|
||||||
},
|
kEndEntry
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PRUint32 nsARIAMap::gWAIRoleMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIRoleMap);
|
PRUint32 nsARIAMap::gWAIRoleMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIRoleMap);
|
||||||
|
@ -510,6 +586,7 @@ nsRoleMapEntry nsARIAMap::gLandmarkRoleMap = {
|
||||||
nsIAccessibleRole::ROLE_NOTHING,
|
nsIAccessibleRole::ROLE_NOTHING,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
};
|
};
|
||||||
|
@ -519,6 +596,7 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
|
||||||
nsIAccessibleRole::ROLE_NOTHING,
|
nsIAccessibleRole::ROLE_NOTHING,
|
||||||
eNoValue,
|
eNoValue,
|
||||||
eNoAction,
|
eNoAction,
|
||||||
|
eNoLiveAttr,
|
||||||
kNoReqStates,
|
kNoReqStates,
|
||||||
kEndEntry
|
kEndEntry
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,6 +63,13 @@ enum EActionRule
|
||||||
eSwitchAction
|
eSwitchAction
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ELiveAttrRule
|
||||||
|
{
|
||||||
|
eNoLiveAttr,
|
||||||
|
eOffLiveAttr,
|
||||||
|
ePoliteLiveAttr
|
||||||
|
};
|
||||||
|
|
||||||
// ARIA attribute characteristic masks, grow as needed
|
// ARIA attribute characteristic masks, grow as needed
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,6 +122,10 @@ struct nsRoleMapEntry
|
||||||
// Action mapping rule, how to expose nsIAccessible action
|
// Action mapping rule, how to expose nsIAccessible action
|
||||||
EActionRule actionRule;
|
EActionRule actionRule;
|
||||||
|
|
||||||
|
// 'live' and 'container-live' object attributes mapping rule: how to expose
|
||||||
|
// these object attributes if ARIA 'live' attribute is missed.
|
||||||
|
ELiveAttrRule liveAttRule;
|
||||||
|
|
||||||
// Automatic state mapping rule: always include in nsIAccessibleStates
|
// Automatic state mapping rule: always include in nsIAccessibleStates
|
||||||
PRUint32 state; // or kNoReqStates if no nsIAccessibleStates are automatic for this role.
|
PRUint32 state; // or kNoReqStates if no nsIAccessibleStates are automatic for this role.
|
||||||
|
|
||||||
|
|
|
@ -272,21 +272,38 @@ nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
|
||||||
nsAutoString atomic, live, relevant, busy;
|
nsAutoString atomic, live, relevant, busy;
|
||||||
nsIContent *ancestor = aStartContent;
|
nsIContent *ancestor = aStartContent;
|
||||||
while (ancestor) {
|
while (ancestor) {
|
||||||
|
|
||||||
|
// container-relevant attribute
|
||||||
if (relevant.IsEmpty() &&
|
if (relevant.IsEmpty() &&
|
||||||
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_relevant) &&
|
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_relevant) &&
|
||||||
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_relevant, relevant))
|
||||||
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerRelevant, relevant);
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerRelevant, relevant);
|
||||||
|
|
||||||
if (live.IsEmpty() &&
|
// container-live attribute
|
||||||
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_live) &&
|
if (live.IsEmpty()) {
|
||||||
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live, live))
|
if (nsAccUtils::HasDefinedARIAToken(ancestor,
|
||||||
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
|
nsAccessibilityAtoms::aria_live)) {
|
||||||
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_live,
|
||||||
|
live);
|
||||||
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
|
||||||
|
} else {
|
||||||
|
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(ancestor));
|
||||||
|
nsRoleMapEntry *role = GetRoleMapEntry(node);
|
||||||
|
if (role) {
|
||||||
|
nsAutoString live;
|
||||||
|
GetLiveAttrValue(role->liveAttRule, live);
|
||||||
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerLive, live);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// container-atomic attribute
|
||||||
if (atomic.IsEmpty() &&
|
if (atomic.IsEmpty() &&
|
||||||
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_atomic) &&
|
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_atomic) &&
|
||||||
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_atomic, atomic))
|
||||||
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerAtomic, atomic);
|
SetAccAttr(aAttributes, nsAccessibilityAtoms::containerAtomic, atomic);
|
||||||
|
|
||||||
|
// container-busy attribute
|
||||||
if (busy.IsEmpty() &&
|
if (busy.IsEmpty() &&
|
||||||
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_busy) &&
|
nsAccUtils::HasDefinedARIAToken(ancestor, nsAccessibilityAtoms::aria_busy) &&
|
||||||
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
|
ancestor->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_busy, busy))
|
||||||
|
@ -669,6 +686,18 @@ nsAccUtils::GetAttributeCharacteristics(nsIAtom* aAtom)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAccUtils::GetLiveAttrValue(PRUint32 aRule, nsAString& aValue)
|
||||||
|
{
|
||||||
|
switch (aRule) {
|
||||||
|
case eOffLiveAttr:
|
||||||
|
aValue = NS_LITERAL_STRING("off");
|
||||||
|
break;
|
||||||
|
case ePoliteLiveAttr:
|
||||||
|
aValue = NS_LITERAL_STRING("polite");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_A11Y
|
#ifdef DEBUG_A11Y
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,12 @@ public:
|
||||||
*/
|
*/
|
||||||
static PRUint8 GetAttributeCharacteristics(nsIAtom* aAtom);
|
static PRUint8 GetAttributeCharacteristics(nsIAtom* aAtom);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the 'live' or 'container-live' object attribute value from the given
|
||||||
|
* ELiveAttrRule constant.
|
||||||
|
*/
|
||||||
|
static void GetLiveAttrValue(PRUint32 aRule, nsAString& aValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query nsAccessNode from the given nsIAccessible.
|
* Query nsAccessNode from the given nsIAccessible.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -256,6 +256,7 @@ ACCESSIBILITY_ATOM(containerBusy, "container-busy")
|
||||||
ACCESSIBILITY_ATOM(containerLive, "container-live")
|
ACCESSIBILITY_ATOM(containerLive, "container-live")
|
||||||
ACCESSIBILITY_ATOM(containerRelevant, "container-relevant")
|
ACCESSIBILITY_ATOM(containerRelevant, "container-relevant")
|
||||||
ACCESSIBILITY_ATOM(level, "level")
|
ACCESSIBILITY_ATOM(level, "level")
|
||||||
|
ACCESSIBILITY_ATOM(live, "live")
|
||||||
ACCESSIBILITY_ATOM(lineNumber, "line-number")
|
ACCESSIBILITY_ATOM(lineNumber, "line-number")
|
||||||
ACCESSIBILITY_ATOM(posinset, "posinset")
|
ACCESSIBILITY_ATOM(posinset, "posinset")
|
||||||
ACCESSIBILITY_ATOM(setsize, "setsize")
|
ACCESSIBILITY_ATOM(setsize, "setsize")
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "nsAccessible.h"
|
#include "nsAccessible.h"
|
||||||
#include "nsAccessibleRelation.h"
|
#include "nsAccessibleRelation.h"
|
||||||
#include "nsHyperTextAccessibleWrap.h"
|
#include "nsHyperTextAccessibleWrap.h"
|
||||||
#include "nsNameUtils.h"
|
|
||||||
|
|
||||||
#include "nsIAccessibleDocument.h"
|
#include "nsIAccessibleDocument.h"
|
||||||
#include "nsIAccessibleHyperText.h"
|
#include "nsIAccessibleHyperText.h"
|
||||||
|
@ -329,7 +328,9 @@ NS_IMETHODIMP nsAccessible::GetDescription(nsAString& aDescription)
|
||||||
}
|
}
|
||||||
if (!content->IsNodeOfType(nsINode::eTEXT)) {
|
if (!content->IsNodeOfType(nsINode::eTEXT)) {
|
||||||
nsAutoString description;
|
nsAutoString description;
|
||||||
nsresult rv = GetTextFromRelationID(nsAccessibilityAtoms::aria_describedby, description);
|
nsresult rv = nsTextEquivUtils::
|
||||||
|
GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_describedby,
|
||||||
|
description);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
PRBool isXUL = content->IsNodeOfType(nsINode::eXUL);
|
PRBool isXUL = content->IsNodeOfType(nsINode::eXUL);
|
||||||
if (isXUL) {
|
if (isXUL) {
|
||||||
|
@ -341,7 +342,8 @@ NS_IMETHODIMP nsAccessible::GetDescription(nsAString& aDescription)
|
||||||
|
|
||||||
if (descriptionContent) {
|
if (descriptionContent) {
|
||||||
// We have a description content node
|
// We have a description content node
|
||||||
AppendFlatStringFromSubtree(descriptionContent, &description);
|
nsTextEquivUtils::
|
||||||
|
AppendTextEquivFromContent(this, descriptionContent, &description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (description.IsEmpty()) {
|
if (description.IsEmpty()) {
|
||||||
|
@ -1456,284 +1458,6 @@ nsAccessible::TakeFocus()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsAccessible::AppendStringWithSpaces(nsAString *aFlatString, const nsAString& textEquivalent)
|
|
||||||
{
|
|
||||||
// Insert spaces to insure that words from controls aren't jammed together
|
|
||||||
if (!textEquivalent.IsEmpty()) {
|
|
||||||
if (!aFlatString->IsEmpty())
|
|
||||||
aFlatString->Append(PRUnichar(' '));
|
|
||||||
aFlatString->Append(textEquivalent);
|
|
||||||
aFlatString->Append(PRUnichar(' '));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult nsAccessible::AppendNameFromAccessibleFor(nsIContent *aContent,
|
|
||||||
nsAString *aFlatString,
|
|
||||||
PRBool aFromValue)
|
|
||||||
{
|
|
||||||
nsAutoString textEquivalent, value;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(aContent));
|
|
||||||
nsCOMPtr<nsIAccessible> accessible;
|
|
||||||
if (domNode == mDOMNode) {
|
|
||||||
accessible = this;
|
|
||||||
if (!aFromValue) {
|
|
||||||
// prevent recursive call GetName()
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nsCOMPtr<nsIAccessibilityService> accService =
|
|
||||||
do_GetService("@mozilla.org/accessibilityService;1");
|
|
||||||
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
|
||||||
accService->GetAccessibleInWeakShell(domNode, mWeakShell, getter_AddRefs(accessible));
|
|
||||||
}
|
|
||||||
if (accessible) {
|
|
||||||
if (aFromValue) {
|
|
||||||
accessible->GetValue(textEquivalent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
accessible->GetName(textEquivalent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textEquivalent.CompressWhitespace();
|
|
||||||
return AppendStringWithSpaces(aFlatString, textEquivalent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AppendFlatStringFromContentNode and AppendFlatStringFromSubtree
|
|
||||||
*
|
|
||||||
* This method will glean useful text, in whatever form it exists, from any content node given to it.
|
|
||||||
* It is used by any decendant of nsAccessible that needs to get text from a single node, as
|
|
||||||
* well as by nsAccessible::AppendFlatStringFromSubtree, which gleans and concatenates text from any node and
|
|
||||||
* that node's decendants.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nsresult nsAccessible::AppendFlatStringFromContentNode(nsIContent *aContent, nsAString *aFlatString)
|
|
||||||
{
|
|
||||||
if (aContent->IsNodeOfType(nsINode::eTEXT)) {
|
|
||||||
// If it's a text node, append the text
|
|
||||||
PRBool isHTMLBlock = PR_FALSE;
|
|
||||||
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
|
||||||
if (!shell) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIContent *parentContent = aContent->GetParent();
|
|
||||||
nsCOMPtr<nsIContent> appendedSubtreeStart(do_QueryInterface(mDOMNode));
|
|
||||||
if (parentContent && parentContent != appendedSubtreeStart) {
|
|
||||||
nsIFrame *frame = shell->GetPrimaryFrameFor(parentContent);
|
|
||||||
if (frame) {
|
|
||||||
// If this text is inside a block level frame (as opposed to span level), we need to add spaces around that
|
|
||||||
// block's text, so we don't get words jammed together in final name
|
|
||||||
// Extra spaces will be trimmed out later
|
|
||||||
const nsStyleDisplay* display = frame->GetStyleDisplay();
|
|
||||||
if (display->IsBlockOutside() ||
|
|
||||||
display->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
|
|
||||||
isHTMLBlock = PR_TRUE;
|
|
||||||
if (!aFlatString->IsEmpty()) {
|
|
||||||
aFlatString->Append(PRUnichar(' '));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (aContent->TextLength() > 0) {
|
|
||||||
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
|
|
||||||
if (frame) {
|
|
||||||
nsresult rv = frame->GetRenderedText(aFlatString);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
} else {
|
|
||||||
//if aContent is an object that is display: none, we have no a frame
|
|
||||||
aContent->AppendTextTo(*aFlatString);
|
|
||||||
}
|
|
||||||
if (isHTMLBlock && !aFlatString->IsEmpty()) {
|
|
||||||
aFlatString->Append(PRUnichar(' '));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString textEquivalent;
|
|
||||||
if (!aContent->IsNodeOfType(nsINode::eHTML)) {
|
|
||||||
if (aContent->IsNodeOfType(nsINode::eXUL)) {
|
|
||||||
nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl(do_QueryInterface(aContent));
|
|
||||||
if (labeledEl) {
|
|
||||||
labeledEl->GetLabel(textEquivalent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (aContent->NodeInfo()->Equals(nsAccessibilityAtoms::label, kNameSpaceID_XUL)) {
|
|
||||||
aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, textEquivalent);
|
|
||||||
}
|
|
||||||
if (textEquivalent.IsEmpty()) {
|
|
||||||
aContent->GetAttr(kNameSpaceID_None,
|
|
||||||
nsAccessibilityAtoms::tooltiptext, textEquivalent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AppendNameFromAccessibleFor(aContent, &textEquivalent, PR_TRUE /* use value */);
|
|
||||||
|
|
||||||
return AppendStringWithSpaces(aFlatString, textEquivalent);
|
|
||||||
}
|
|
||||||
return NS_OK; // Not HTML and not XUL -- we don't handle it yet
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIAtom> tag = aContent->Tag();
|
|
||||||
if (tag == nsAccessibilityAtoms::img) {
|
|
||||||
return AppendNameFromAccessibleFor(aContent, aFlatString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag == nsAccessibilityAtoms::input) {
|
|
||||||
static nsIContent::AttrValuesArray strings[] =
|
|
||||||
{&nsAccessibilityAtoms::button, &nsAccessibilityAtoms::submit,
|
|
||||||
&nsAccessibilityAtoms::reset, &nsAccessibilityAtoms::image, nsnull};
|
|
||||||
if (aContent->FindAttrValueIn(kNameSpaceID_None, nsAccessibilityAtoms::type,
|
|
||||||
strings, eIgnoreCase) >= 0) {
|
|
||||||
return AppendNameFromAccessibleFor(aContent, aFlatString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag == nsAccessibilityAtoms::object && !aContent->GetChildCount()) {
|
|
||||||
// If object has no alternative content children, try title
|
|
||||||
aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::title, textEquivalent);
|
|
||||||
}
|
|
||||||
else if (tag == nsAccessibilityAtoms::br) {
|
|
||||||
// If it's a line break, insert a space so that words aren't jammed together
|
|
||||||
aFlatString->AppendLiteral("\r\n");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
else if (tag != nsAccessibilityAtoms::a && tag != nsAccessibilityAtoms::area) {
|
|
||||||
AppendNameFromAccessibleFor(aContent, aFlatString, PR_TRUE /* use value */);
|
|
||||||
}
|
|
||||||
|
|
||||||
textEquivalent.CompressWhitespace();
|
|
||||||
return AppendStringWithSpaces(aFlatString, textEquivalent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
nsresult nsAccessible::AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString)
|
|
||||||
{
|
|
||||||
static PRBool isAlreadyHere; // Prevent recursion which can cause infinite loops
|
|
||||||
if (isAlreadyHere) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
isAlreadyHere = PR_TRUE;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
|
||||||
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
|
|
||||||
PRBool isHidden = (!frame || !frame->GetStyleVisibility()->IsVisible());
|
|
||||||
nsresult rv = AppendFlatStringFromSubtreeRecurse(aContent, aFlatString,
|
|
||||||
isHidden);
|
|
||||||
|
|
||||||
isAlreadyHere = PR_FALSE;
|
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && !aFlatString->IsEmpty()) {
|
|
||||||
nsAString::const_iterator start, end;
|
|
||||||
aFlatString->BeginReading(start);
|
|
||||||
aFlatString->EndReading(end);
|
|
||||||
|
|
||||||
PRInt32 spacesToTruncate = 0;
|
|
||||||
while (-- end != start && *end == ' ')
|
|
||||||
++ spacesToTruncate;
|
|
||||||
|
|
||||||
if (spacesToTruncate > 0)
|
|
||||||
aFlatString->Truncate(aFlatString->Length() - spacesToTruncate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsAccessible::AppendFlatStringFromSubtreeRecurse(nsIContent *aContent,
|
|
||||||
nsAString *aFlatString,
|
|
||||||
PRBool aIsRootHidden)
|
|
||||||
{
|
|
||||||
// Depth first search for all text nodes that are decendants of content node.
|
|
||||||
// Append all the text into one flat string
|
|
||||||
PRUint32 numChildren = 0;
|
|
||||||
nsCOMPtr<nsIDOMXULSelectControlElement> selectControlEl(do_QueryInterface(aContent));
|
|
||||||
nsCOMPtr<nsIAtom> tag = aContent->Tag();
|
|
||||||
|
|
||||||
if (!selectControlEl &&
|
|
||||||
tag != nsAccessibilityAtoms::textarea &&
|
|
||||||
tag != nsAccessibilityAtoms::select) {
|
|
||||||
// Don't walk children of elements with options, just get label directly.
|
|
||||||
// Don't traverse the children of a textarea, we want the value, not the
|
|
||||||
// static text node.
|
|
||||||
// Don't traverse the children of a select element, we only want the
|
|
||||||
// current value.
|
|
||||||
numChildren = aContent->GetChildCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numChildren == 0) {
|
|
||||||
// There are no children or they are irrelvant: get the text from the current node
|
|
||||||
AppendFlatStringFromContentNode(aContent, aFlatString);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are relevant children: use them to get the text.
|
|
||||||
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
|
||||||
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
PRUint32 index;
|
|
||||||
for (index = 0; index < numChildren; index++) {
|
|
||||||
nsCOMPtr<nsIContent> childContent = aContent->GetChildAt(index);
|
|
||||||
|
|
||||||
// Walk into hidden subtree if the the root parent is also hidden. This
|
|
||||||
// happens when the author explictly uses a hidden label or description.
|
|
||||||
if (!aIsRootHidden) {
|
|
||||||
nsIFrame *childFrame = shell->GetPrimaryFrameFor(childContent);
|
|
||||||
if (!childFrame || !childFrame->GetStyleVisibility()->IsVisible())
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
AppendFlatStringFromSubtreeRecurse(childContent, aFlatString,
|
|
||||||
aIsRootHidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult nsAccessible::GetTextFromRelationID(nsIAtom *aIDProperty, nsString &aName)
|
|
||||||
{
|
|
||||||
// Get DHTML name from content subtree pointed to by ID attribute
|
|
||||||
aName.Truncate();
|
|
||||||
NS_ASSERTION(mDOMNode, "Called from shutdown accessible");
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode);
|
|
||||||
if (!content)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIArray> refElms;
|
|
||||||
nsCoreUtils::GetElementsByIDRefsAttr(content, aIDProperty,
|
|
||||||
getter_AddRefs(refElms));
|
|
||||||
|
|
||||||
if (!refElms)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
PRUint32 count = 0;
|
|
||||||
nsresult rv = refElms->GetLength(&count);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> refContent;
|
|
||||||
for (PRUint32 idx = 0; idx < count; idx++) {
|
|
||||||
refContent = do_QueryElementAt(refElms, idx, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (!aName.IsEmpty())
|
|
||||||
aName += ' '; // Need whitespace between multiple labels or descriptions
|
|
||||||
|
|
||||||
rv = AppendFlatStringFromSubtree(refContent, &aName);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
aName.CompressWhitespace();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsAccessible::GetHTMLName(nsAString& aLabel)
|
nsAccessible::GetHTMLName(nsAString& aLabel)
|
||||||
{
|
{
|
||||||
|
@ -1746,7 +1470,8 @@ nsAccessible::GetHTMLName(nsAString& aLabel)
|
||||||
nsIContent *labelContent = nsCoreUtils::GetHTMLLabelContent(content);
|
nsIContent *labelContent = nsCoreUtils::GetHTMLLabelContent(content);
|
||||||
if (labelContent) {
|
if (labelContent) {
|
||||||
nsAutoString label;
|
nsAutoString label;
|
||||||
nsresult rv = AppendFlatStringFromSubtree(labelContent, &label);
|
nsresult rv =
|
||||||
|
nsTextEquivUtils::AppendTextEquivFromContent(this, labelContent, &label);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
label.CompressWhitespace();
|
label.CompressWhitespace();
|
||||||
|
@ -1756,20 +1481,7 @@ nsAccessible::GetHTMLName(nsAString& aLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 role = nsAccUtils::Role(this);
|
return nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
|
||||||
PRUint32 canAggregateName =
|
|
||||||
nsNameUtils::gRoleToNameRulesMap[role] & eFromSubtree;
|
|
||||||
|
|
||||||
if (canAggregateName) {
|
|
||||||
// Don't use AppendFlatStringFromSubtree for container widgets like menulist
|
|
||||||
nsresult rv = AppendFlatStringFromSubtree(content, &aLabel);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (!aLabel.IsEmpty())
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1829,7 +1541,7 @@ nsAccessible::GetXULName(nsAString& aLabel)
|
||||||
if (xulLabel && NS_SUCCEEDED(xulLabel->GetValue(label)) && label.IsEmpty()) {
|
if (xulLabel && NS_SUCCEEDED(xulLabel->GetValue(label)) && label.IsEmpty()) {
|
||||||
// If no value attribute, a non-empty label must contain
|
// If no value attribute, a non-empty label must contain
|
||||||
// children that define its text -- possibly using HTML
|
// children that define its text -- possibly using HTML
|
||||||
AppendFlatStringFromSubtree(labelContent, &label);
|
nsTextEquivUtils::AppendTextEquivFromContent(this, labelContent, &label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1854,12 +1566,7 @@ nsAccessible::GetXULName(nsAString& aLabel)
|
||||||
parent = parent->GetParent();
|
parent = parent->GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 role = nsAccUtils::Role(this);
|
return nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
|
||||||
PRUint32 canAggregateName =
|
|
||||||
nsNameUtils::gRoleToNameRulesMap[role] & eFromSubtree;
|
|
||||||
|
|
||||||
return canAggregateName ?
|
|
||||||
AppendFlatStringFromSubtree(content, &aLabel) : NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -1926,7 +1633,8 @@ NS_IMETHODIMP nsAccessible::GetFinalRole(PRUint32 *aRole)
|
||||||
// gLandmarkRoleMap: can use role of accessible class impl
|
// gLandmarkRoleMap: can use role of accessible class impl
|
||||||
// gEmptyRoleMap and all others: cannot use role of accessible class impl
|
// gEmptyRoleMap and all others: cannot use role of accessible class impl
|
||||||
if (mRoleMapEntry != &nsARIAMap::gLandmarkRoleMap) {
|
if (mRoleMapEntry != &nsARIAMap::gLandmarkRoleMap) {
|
||||||
// We can now expose ROLE_NOTHING when there is a role map entry, which
|
// We can now expose ROLE_NOTHING when there is a role map entry or used
|
||||||
|
// role is nothing, which
|
||||||
// will cause ATK to use ROLE_UNKNOWN and MSAA to use a BSTR role with
|
// will cause ATK to use ROLE_UNKNOWN and MSAA to use a BSTR role with
|
||||||
// the ARIA role or element's tag. In either case the AT can also use
|
// the ARIA role or element's tag. In either case the AT can also use
|
||||||
// the object attributes tag and xml-roles to find out more.
|
// the object attributes tag and xml-roles to find out more.
|
||||||
|
@ -2012,7 +1720,7 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose all ARIA attributes
|
// Expose object attributes from ARIA attributes.
|
||||||
PRUint32 numAttrs = content->GetAttrCount();
|
PRUint32 numAttrs = content->GetAttrCount();
|
||||||
for (PRUint32 count = 0; count < numAttrs; count ++) {
|
for (PRUint32 count = 0; count < numAttrs; count ++) {
|
||||||
const nsAttrName *attr = content->GetAttrNameAt(count);
|
const nsAttrName *attr = content->GetAttrNameAt(count);
|
||||||
|
@ -2035,6 +1743,17 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is no aria-live attribute then expose default value of 'live'
|
||||||
|
// object attribute used for ARIA role of this accessible.
|
||||||
|
if (mRoleMapEntry) {
|
||||||
|
nsAutoString live;
|
||||||
|
nsAccUtils::GetAccAttr(attributes, nsAccessibilityAtoms::live, live);
|
||||||
|
if (live.IsEmpty()) {
|
||||||
|
nsAccUtils::GetLiveAttrValue(mRoleMapEntry->liveAttRule, live);
|
||||||
|
nsAccUtils::SetAccAttr(attributes, nsAccessibilityAtoms::live, live);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3378,14 +3097,18 @@ nsAccessible::GetARIAName(nsAString& aName)
|
||||||
// First check for label override via aria-label property
|
// First check for label override via aria-label property
|
||||||
nsAutoString label;
|
nsAutoString label;
|
||||||
if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_label, label)) {
|
if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_label, label)) {
|
||||||
|
label.CompressWhitespace();
|
||||||
aName = label;
|
aName = label;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second check for label override via aria-labelledby relationship
|
// Second check for label override via aria-labelledby relationship
|
||||||
nsresult rv = GetTextFromRelationID(nsAccessibilityAtoms::aria_labelledby, label);
|
nsresult rv = nsTextEquivUtils::
|
||||||
if (NS_SUCCEEDED(rv))
|
GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_labelledby, label);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
label.CompressWhitespace();
|
||||||
aName = label;
|
aName = label;
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
|
|
||||||
#include "nsAccessNodeWrap.h"
|
#include "nsAccessNodeWrap.h"
|
||||||
|
|
||||||
|
#include "nsARIAMap.h"
|
||||||
|
#include "nsRelUtils.h"
|
||||||
|
#include "nsTextEquivUtils.h"
|
||||||
|
|
||||||
#include "nsIAccessible.h"
|
#include "nsIAccessible.h"
|
||||||
#include "nsPIAccessible.h"
|
#include "nsPIAccessible.h"
|
||||||
#include "nsIAccessibleHyperLink.h"
|
#include "nsIAccessibleHyperLink.h"
|
||||||
|
@ -50,15 +54,12 @@
|
||||||
#include "nsIAccessibleStates.h"
|
#include "nsIAccessibleStates.h"
|
||||||
#include "nsIAccessibleEvent.h"
|
#include "nsIAccessibleEvent.h"
|
||||||
|
|
||||||
#include "nsRelUtils.h"
|
|
||||||
|
|
||||||
#include "nsIDOMNodeList.h"
|
#include "nsIDOMNodeList.h"
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
#include "nsWeakReference.h"
|
#include "nsWeakReference.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsIDOMDOMStringList.h"
|
#include "nsIDOMDOMStringList.h"
|
||||||
#include "nsARIAMap.h"
|
|
||||||
|
|
||||||
struct nsRect;
|
struct nsRect;
|
||||||
class nsIContent;
|
class nsIContent;
|
||||||
|
@ -181,18 +182,6 @@ protected:
|
||||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||||
PRBool IsVisible(PRBool *aIsOffscreen);
|
PRBool IsVisible(PRBool *aIsOffscreen);
|
||||||
|
|
||||||
// Relation helpers
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For a given ARIA relation, such as labelledby or describedby, get the collated text
|
|
||||||
* for the subtree that's pointed to.
|
|
||||||
*
|
|
||||||
* @param aIDProperty The ARIA relationship property to get the text for
|
|
||||||
* @param aName Where to put the text
|
|
||||||
* @return error or success code
|
|
||||||
*/
|
|
||||||
nsresult GetTextFromRelationID(nsIAtom *aIDProperty, nsString &aName);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Name helpers.
|
// Name helpers.
|
||||||
|
|
||||||
|
@ -206,14 +195,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult GetXULName(nsAString& aName);
|
nsresult GetXULName(nsAString& aName);
|
||||||
|
|
||||||
// For accessibles that are not lists of choices, the name of the subtree should be the
|
|
||||||
// sum of names in the subtree
|
|
||||||
nsresult AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString);
|
|
||||||
nsresult AppendNameFromAccessibleFor(nsIContent *aContent, nsAString *aFlatString,
|
|
||||||
PRBool aFromValue = PR_FALSE);
|
|
||||||
nsresult AppendFlatStringFromContentNode(nsIContent *aContent, nsAString *aFlatString);
|
|
||||||
nsresult AppendStringWithSpaces(nsAString *aFlatString, const nsAString& textEquivalent);
|
|
||||||
|
|
||||||
// helper method to verify frames
|
// helper method to verify frames
|
||||||
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
|
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
|
||||||
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
|
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
|
||||||
|
|
|
@ -344,7 +344,7 @@ nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
|
||||||
rect += offsetFromWidget;
|
rect += offsetFromWidget;
|
||||||
caretRect = nsRect::ToOutsidePixels(rect, presContext->AppUnitsPerDevPixel());
|
caretRect = nsRect::ToOutsidePixels(rect, presContext->AppUnitsPerDevPixel());
|
||||||
|
|
||||||
(*aOutWidget)->WidgetToScreen(caretRect, caretRect);
|
caretRect.MoveBy((*aOutWidget)->WidgetToScreenOffset());
|
||||||
|
|
||||||
// Correct for character size, so that caret always matches the size of the character
|
// Correct for character size, so that caret always matches the size of the character
|
||||||
// This is important for font size transitions, and is necessary because the Gecko caret uses the
|
// This is important for font size transitions, and is necessary because the Gecko caret uses the
|
||||||
|
|
|
@ -263,7 +263,9 @@ nsDocAccessible::GetDescription(nsAString& aDescription)
|
||||||
|
|
||||||
if (aDescription.IsEmpty()) {
|
if (aDescription.IsEmpty()) {
|
||||||
nsAutoString description;
|
nsAutoString description;
|
||||||
GetTextFromRelationID(nsAccessibilityAtoms::aria_describedby, description);
|
nsTextEquivUtils::
|
||||||
|
GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_describedby,
|
||||||
|
description);
|
||||||
aDescription = description;
|
aDescription = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,169 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
|
||||||
*/
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#include "nsNameUtils.h"
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Name rules to role map.
|
|
||||||
|
|
||||||
PRUint32 nsNameUtils::gRoleToNameRulesMap[] =
|
|
||||||
{
|
|
||||||
eNoRule, // ROLE_NOTHING
|
|
||||||
eNoRule, // ROLE_TITLEBAR
|
|
||||||
eNoRule, // ROLE_MENUBAR
|
|
||||||
eNoRule, // ROLE_SCROLLBAR
|
|
||||||
eNoRule, // ROLE_GRIP
|
|
||||||
eNoRule, // ROLE_SOUND
|
|
||||||
eNoRule, // ROLE_CURSOR
|
|
||||||
eNoRule, // ROLE_CARET
|
|
||||||
eNoRule, // ROLE_ALERT
|
|
||||||
eNoRule, // ROLE_WINDOW
|
|
||||||
eNoRule, // ROLE_INTERNAL_FRAME
|
|
||||||
eNoRule, // ROLE_MENUPOPUP
|
|
||||||
eFromSubtree, // ROLE_MENUITEM
|
|
||||||
eFromSubtree, // ROLE_TOOLTIP
|
|
||||||
eNoRule, // ROLE_APPLICATION
|
|
||||||
eNoRule, // ROLE_DOCUMENT
|
|
||||||
eNoRule, // ROLE_PANE
|
|
||||||
eNoRule, // ROLE_CHART
|
|
||||||
eNoRule, // ROLE_DIALOG
|
|
||||||
eNoRule, // ROLE_BORDER
|
|
||||||
eNoRule, // ROLE_GROUPING
|
|
||||||
eNoRule, // ROLE_SEPARATOR
|
|
||||||
eNoRule, // ROLE_TOOLBAR
|
|
||||||
eNoRule, // ROLE_STATUSBAR
|
|
||||||
eNoRule, // ROLE_TABLE
|
|
||||||
eFromSubtree, // ROLE_COLUMNHEADER
|
|
||||||
eFromSubtree, // ROLE_ROWHEADER
|
|
||||||
eFromSubtree, // ROLE_COLUMN
|
|
||||||
eFromSubtree, // ROLE_ROW
|
|
||||||
eNoRule, // ROLE_CELL
|
|
||||||
eFromSubtree, // ROLE_LINK
|
|
||||||
eFromSubtree, // ROLE_HELPBALLOON
|
|
||||||
eNoRule, // ROLE_CHARACTER
|
|
||||||
eNoRule, // ROLE_LIST
|
|
||||||
eFromSubtree, // ROLE_LISTITEM
|
|
||||||
eNoRule, // ROLE_OUTLINE
|
|
||||||
eFromSubtree, // ROLE_OUTLINEITEM
|
|
||||||
eFromSubtree, // ROLE_PAGETAB
|
|
||||||
eNoRule, // ROLE_PROPERTYPAGE
|
|
||||||
eNoRule, // ROLE_INDICATOR
|
|
||||||
eNoRule, // ROLE_GRAPHIC
|
|
||||||
eNoRule, // ROLE_STATICTEXT
|
|
||||||
eNoRule, // ROLE_TEXT_LEAF
|
|
||||||
eFromSubtree, // ROLE_PUSHBUTTON
|
|
||||||
eFromSubtree, // ROLE_CHECKBUTTON
|
|
||||||
eFromSubtree, // ROLE_RADIOBUTTON
|
|
||||||
eNoRule, // ROLE_COMBOBOX
|
|
||||||
eNoRule, // ROLE_DROPLIST
|
|
||||||
eNoRule, // ROLE_PROGRESSBAR
|
|
||||||
eNoRule, // ROLE_DIAL
|
|
||||||
eNoRule, // ROLE_HOTKEYFIELD
|
|
||||||
eNoRule, // ROLE_SLIDER
|
|
||||||
eNoRule, // ROLE_SPINBUTTON
|
|
||||||
eNoRule, // ROLE_DIAGRAM
|
|
||||||
eNoRule, // ROLE_ANIMATION
|
|
||||||
eNoRule, // ROLE_EQUATION
|
|
||||||
eFromSubtree, // ROLE_BUTTONDROPDOWN
|
|
||||||
eFromSubtree, // ROLE_BUTTONMENU
|
|
||||||
eFromSubtree, // ROLE_BUTTONDROPDOWNGRID
|
|
||||||
eNoRule, // ROLE_WHITESPACE
|
|
||||||
eNoRule, // ROLE_PAGETABLIST
|
|
||||||
eNoRule, // ROLE_CLOCK
|
|
||||||
eNoRule, // ROLE_SPLITBUTTON
|
|
||||||
eNoRule, // ROLE_IPADDRESS
|
|
||||||
eNoRule, // ROLE_ACCEL_LABEL
|
|
||||||
eNoRule, // ROLE_ARROW
|
|
||||||
eNoRule, // ROLE_CANVAS
|
|
||||||
eFromSubtree, // ROLE_CHECK_MENU_ITEM
|
|
||||||
eNoRule, // ROLE_COLOR_CHOOSER
|
|
||||||
eNoRule, // ROLE_DATE_EDITOR
|
|
||||||
eNoRule, // ROLE_DESKTOP_ICON
|
|
||||||
eNoRule, // ROLE_DESKTOP_FRAME
|
|
||||||
eNoRule, // ROLE_DIRECTORY_PANE
|
|
||||||
eNoRule, // ROLE_FILE_CHOOSER
|
|
||||||
eNoRule, // ROLE_FONT_CHOOSER
|
|
||||||
eNoRule, // ROLE_CHROME_WINDOW
|
|
||||||
eNoRule, // ROLE_GLASS_PANE
|
|
||||||
eNoRule, // ROLE_HTML_CONTAINER
|
|
||||||
eNoRule, // ROLE_ICON
|
|
||||||
eNoRule, // ROLE_LABEL
|
|
||||||
eNoRule, // ROLE_LAYERED_PANE
|
|
||||||
eNoRule, // ROLE_OPTION_PANE
|
|
||||||
eNoRule, // ROLE_PASSWORD_TEXT
|
|
||||||
eNoRule, // ROLE_POPUP_MENU
|
|
||||||
eFromSubtree, // ROLE_RADIO_MENU_ITEM
|
|
||||||
eNoRule, // ROLE_ROOT_PANE
|
|
||||||
eNoRule, // ROLE_SCROLL_PANE
|
|
||||||
eNoRule, // ROLE_SPLIT_PANE
|
|
||||||
eFromSubtree, // ROLE_TABLE_COLUMN_HEADER
|
|
||||||
eFromSubtree, // ROLE_TABLE_ROW_HEADER
|
|
||||||
eFromSubtree, // ROLE_TEAR_OFF_MENU_ITEM
|
|
||||||
eNoRule, // ROLE_TERMINAL
|
|
||||||
eNoRule, // ROLE_TEXT_CONTAINER
|
|
||||||
eFromSubtree, // ROLE_TOGGLE_BUTTON
|
|
||||||
eNoRule, // ROLE_TREE_TABLE
|
|
||||||
eNoRule, // ROLE_VIEWPORT
|
|
||||||
eNoRule, // ROLE_HEADER
|
|
||||||
eNoRule, // ROLE_FOOTER
|
|
||||||
eNoRule, // ROLE_PARAGRAPH
|
|
||||||
eNoRule, // ROLE_RULER
|
|
||||||
eNoRule, // ROLE_AUTOCOMPLETE
|
|
||||||
eNoRule, // ROLE_EDITBAR
|
|
||||||
eNoRule, // ROLE_ENTRY
|
|
||||||
eNoRule, // ROLE_CAPTION
|
|
||||||
eNoRule, // ROLE_DOCUMENT_FRAME
|
|
||||||
eNoRule, // ROLE_HEADING
|
|
||||||
eNoRule, // ROLE_PAGE
|
|
||||||
eNoRule, // ROLE_SECTION
|
|
||||||
eNoRule, // ROLE_REDUNDANT_OBJECT
|
|
||||||
eNoRule, // ROLE_FORM
|
|
||||||
eNoRule, // ROLE_IME
|
|
||||||
eNoRule, // ROLE_APP_ROOT
|
|
||||||
eFromSubtree, // ROLE_PARENT_MENUITEM
|
|
||||||
eNoRule, // ROLE_CALENDAR
|
|
||||||
eNoRule, // ROLE_COMBOBOX_LIST
|
|
||||||
eFromSubtree, // ROLE_COMBOBOX_OPTION
|
|
||||||
eNoRule, // ROLE_IMAGE_MAP
|
|
||||||
eFromSubtree, // ROLE_OPTION
|
|
||||||
eFromSubtree, // ROLE_RICH_OPTION
|
|
||||||
eNoRule, // ROLE_LISTBOX
|
|
||||||
eNoRule, // ROLE_FLAT_EQUATION
|
|
||||||
eFromSubtree // ROLE_GRID_CELL
|
|
||||||
};
|
|
|
@ -1,71 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
|
||||||
*/
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef _nsNameUtils_H_
|
|
||||||
#define _nsNameUtils_H_
|
|
||||||
|
|
||||||
#include "prtypes.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name from subtree calculation rules.
|
|
||||||
*/
|
|
||||||
enum ENameFromSubtreeRule
|
|
||||||
{
|
|
||||||
// do not walk into subtree to compute the name
|
|
||||||
eNoRule = 0x00,
|
|
||||||
|
|
||||||
// compute the name from the subtree
|
|
||||||
eFromSubtree = 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class provides utils methods to compute the accessible name and
|
|
||||||
* description.
|
|
||||||
*/
|
|
||||||
class nsNameUtils
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map array from roles to name rules (bit state of ENameFromSubtreeRule).
|
|
||||||
*/
|
|
||||||
static PRUint32 gRoleToNameRulesMap[];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,508 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||||
|
*/
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsTextEquivUtils.h"
|
||||||
|
|
||||||
|
#include "nsAccessible.h"
|
||||||
|
|
||||||
|
#include "nsIDOMXULLabeledControlEl.h"
|
||||||
|
|
||||||
|
#include "nsArrayUtils.h"
|
||||||
|
|
||||||
|
#define NS_OK_NO_NAME_CLAUSE_HANDLED \
|
||||||
|
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 0x24)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// nsTextEquivUtils. Public.
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::GetNameFromSubtree(nsIAccessible *aAccessible,
|
||||||
|
nsAString& aName)
|
||||||
|
{
|
||||||
|
aName.Truncate();
|
||||||
|
|
||||||
|
if (gInitiatorAcc)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
gInitiatorAcc = aAccessible;
|
||||||
|
|
||||||
|
PRUint32 role = nsAccUtils::Role(aAccessible);
|
||||||
|
PRUint32 nameRule = gRoleToNameRulesMap[role];
|
||||||
|
|
||||||
|
if (nameRule == eFromSubtree) {
|
||||||
|
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> DOMNode;
|
||||||
|
accessNode->GetDOMNode(getter_AddRefs(DOMNode));
|
||||||
|
nsCOMPtr<nsIContent> content(do_QueryInterface(DOMNode));
|
||||||
|
if (content) {
|
||||||
|
nsAutoString name;
|
||||||
|
AppendFromAccessibleChildren(aAccessible, &name);
|
||||||
|
name.CompressWhitespace();
|
||||||
|
aName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gInitiatorAcc = nsnull;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::GetTextEquivFromIDRefs(nsIAccessible *aAccessible,
|
||||||
|
nsIAtom *aIDRefsAttr,
|
||||||
|
nsAString& aTextEquiv)
|
||||||
|
{
|
||||||
|
aTextEquiv.Truncate();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> DOMNode;
|
||||||
|
accessNode->GetDOMNode(getter_AddRefs(DOMNode));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(DOMNode);
|
||||||
|
if (!content)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIArray> refElms;
|
||||||
|
nsCoreUtils::GetElementsByIDRefsAttr(content, aIDRefsAttr,
|
||||||
|
getter_AddRefs(refElms));
|
||||||
|
|
||||||
|
if (!refElms)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
PRUint32 count = 0;
|
||||||
|
nsresult rv = refElms->GetLength(&count);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> refContent;
|
||||||
|
for (PRUint32 idx = 0; idx < count; idx++) {
|
||||||
|
refContent = do_QueryElementAt(refElms, idx, &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (!aTextEquiv.IsEmpty())
|
||||||
|
aTextEquiv += ' ';
|
||||||
|
|
||||||
|
rv = AppendTextEquivFromContent(aAccessible, refContent, &aTextEquiv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::AppendTextEquivFromContent(nsIAccessible *aInitiatorAcc,
|
||||||
|
nsIContent *aContent,
|
||||||
|
nsAString *aString)
|
||||||
|
{
|
||||||
|
// Prevent recursion which can cause infinite loops.
|
||||||
|
if (gInitiatorAcc)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
gInitiatorAcc = aInitiatorAcc;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(aContent));
|
||||||
|
nsCOMPtr<nsIPresShell> shell = nsCoreUtils::GetPresShellFor(DOMNode);
|
||||||
|
if (!shell) {
|
||||||
|
NS_ASSERTION(PR_TRUE, "There is no presshell!");
|
||||||
|
gInitiatorAcc = nsnull;
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the given content is not visible or isn't accessible then go down
|
||||||
|
// through the DOM subtree otherwise go down through accessible subtree and
|
||||||
|
// calculate the flat string.
|
||||||
|
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
|
||||||
|
PRBool isVisible = frame && frame->GetStyleVisibility()->IsVisible();
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
PRBool goThroughDOMSubtree = PR_TRUE;
|
||||||
|
|
||||||
|
if (isVisible) {
|
||||||
|
nsCOMPtr<nsIAccessible> accessible;
|
||||||
|
rv = nsAccessNode::GetAccService()->
|
||||||
|
GetAccessibleInShell(DOMNode, shell, getter_AddRefs(accessible));
|
||||||
|
if (NS_SUCCEEDED(rv) && accessible) {
|
||||||
|
rv = AppendFromAccessible(accessible, aString);
|
||||||
|
goThroughDOMSubtree = PR_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (goThroughDOMSubtree)
|
||||||
|
rv = AppendFromDOMNode(aContent, aString);
|
||||||
|
|
||||||
|
gInitiatorAcc = nsnull;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::AppendTextEquivFromTextContent(nsIContent *aContent,
|
||||||
|
nsAString *aString)
|
||||||
|
{
|
||||||
|
if (aContent->IsNodeOfType(nsINode::eTEXT)) {
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(aContent));
|
||||||
|
|
||||||
|
PRBool isHTMLBlock = PR_FALSE;
|
||||||
|
nsCOMPtr<nsIPresShell> shell = nsCoreUtils::GetPresShellFor(DOMNode);
|
||||||
|
NS_ENSURE_STATE(shell);
|
||||||
|
|
||||||
|
nsIContent *parentContent = aContent->GetParent();
|
||||||
|
if (parentContent) {
|
||||||
|
nsIFrame *frame = shell->GetPrimaryFrameFor(parentContent);
|
||||||
|
if (frame) {
|
||||||
|
// If this text is inside a block level frame (as opposed to span
|
||||||
|
// level), we need to add spaces around that block's text, so we don't
|
||||||
|
// get words jammed together in final name.
|
||||||
|
const nsStyleDisplay* display = frame->GetStyleDisplay();
|
||||||
|
if (display->IsBlockOutside() ||
|
||||||
|
display->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
|
||||||
|
isHTMLBlock = PR_TRUE;
|
||||||
|
if (!aString->IsEmpty()) {
|
||||||
|
aString->Append(PRUnichar(' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aContent->TextLength() > 0) {
|
||||||
|
nsIFrame *frame = shell->GetPrimaryFrameFor(aContent);
|
||||||
|
if (frame) {
|
||||||
|
nsresult rv = frame->GetRenderedText(aString);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
} else {
|
||||||
|
// If aContent is an object that is display: none, we have no a frame.
|
||||||
|
aContent->AppendTextTo(*aString);
|
||||||
|
}
|
||||||
|
if (isHTMLBlock && !aString->IsEmpty()) {
|
||||||
|
aString->Append(PRUnichar(' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aContent->IsNodeOfType(nsINode::eHTML) &&
|
||||||
|
aContent->NodeInfo()->Equals(nsAccessibilityAtoms::br)) {
|
||||||
|
aString->AppendLiteral("\r\n");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK_NO_NAME_CLAUSE_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// nsTextEquivUtils. Private.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAccessible> nsTextEquivUtils::gInitiatorAcc;
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::AppendFromAccessibleChildren(nsIAccessible *aAccessible,
|
||||||
|
nsAString *aString)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAccessible> accChild, accNextChild;
|
||||||
|
aAccessible->GetFirstChild(getter_AddRefs(accChild));
|
||||||
|
|
||||||
|
while (accChild) {
|
||||||
|
nsresult rv = AppendFromAccessible(accChild, aString);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
accChild->GetNextSibling(getter_AddRefs(accNextChild));
|
||||||
|
accChild.swap(accNextChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::AppendFromAccessible(nsIAccessible *aAccessible,
|
||||||
|
nsAString *aString)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> DOMNode;
|
||||||
|
accessNode->GetDOMNode(getter_AddRefs(DOMNode));
|
||||||
|
nsCOMPtr<nsIContent> content(do_QueryInterface(DOMNode));
|
||||||
|
NS_ASSERTION(content, "There is no content!");
|
||||||
|
|
||||||
|
if (content) {
|
||||||
|
nsresult rv = AppendTextEquivFromTextContent(content, aString);
|
||||||
|
if (rv != NS_OK_NO_NAME_CLAUSE_HANDLED)
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString text;
|
||||||
|
nsresult rv = aAccessible->GetName(text);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
AppendString(aString, text);
|
||||||
|
|
||||||
|
PRUint32 role = nsAccUtils::Role(aAccessible);
|
||||||
|
PRUint32 nameRule = gRoleToNameRulesMap[role];
|
||||||
|
|
||||||
|
if (nameRule == eFromValue) {
|
||||||
|
// Implementation of step f) of text equivalent computation. If the given
|
||||||
|
// accessible is not root accessible (the accessible the text equivalent is
|
||||||
|
// computed for in the end) then append accessible value. Otherwise append
|
||||||
|
// value if and only if the given accessible is in the middle of its parent.
|
||||||
|
|
||||||
|
if (aAccessible != gInitiatorAcc) {
|
||||||
|
rv = aAccessible->GetValue(text);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
AppendString(aString, text);
|
||||||
|
} else {
|
||||||
|
nsCOMPtr<nsIAccessible> nextSibling;
|
||||||
|
aAccessible->GetNextSibling(getter_AddRefs(nextSibling));
|
||||||
|
if (nextSibling) {
|
||||||
|
nsCOMPtr<nsIAccessible> parent;
|
||||||
|
aAccessible->GetParent(getter_AddRefs(parent));
|
||||||
|
if (parent) {
|
||||||
|
nsCOMPtr<nsIAccessible> firstChild;
|
||||||
|
parent->GetFirstChild(getter_AddRefs(firstChild));
|
||||||
|
if (firstChild && firstChild != aAccessible) {
|
||||||
|
rv = aAccessible->GetValue(text);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
AppendString(aString, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of g) step of text equivalent computation guide. Go down
|
||||||
|
// into subtree if accessible allows "text equivalent from subtree rule" or
|
||||||
|
// it's not root and not control.
|
||||||
|
if (text.IsEmpty() && (nameRule & eFromSubtreeIfRec))
|
||||||
|
return AppendFromAccessibleChildren(aAccessible, aString);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::AppendFromDOMChildren(nsIContent *aContent,
|
||||||
|
nsAString *aString)
|
||||||
|
{
|
||||||
|
PRUint32 childCount = aContent->GetChildCount();
|
||||||
|
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||||
|
nsCOMPtr<nsIContent> childContent = aContent->GetChildAt(childIdx);
|
||||||
|
|
||||||
|
nsresult rv = AppendFromDOMNode(childContent, aString);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsTextEquivUtils::AppendFromDOMNode(nsIContent *aContent, nsAString *aString)
|
||||||
|
{
|
||||||
|
nsresult rv = AppendTextEquivFromTextContent(aContent, aString);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (rv != NS_OK_NO_NAME_CLAUSE_HANDLED)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
if (aContent->IsNodeOfType(nsINode::eXUL)) {
|
||||||
|
nsAutoString textEquivalent;
|
||||||
|
nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl =
|
||||||
|
do_QueryInterface(aContent);
|
||||||
|
|
||||||
|
if (labeledEl) {
|
||||||
|
labeledEl->GetLabel(textEquivalent);
|
||||||
|
} else {
|
||||||
|
if (aContent->NodeInfo()->Equals(nsAccessibilityAtoms::label,
|
||||||
|
kNameSpaceID_XUL))
|
||||||
|
aContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value,
|
||||||
|
textEquivalent);
|
||||||
|
|
||||||
|
if (textEquivalent.IsEmpty())
|
||||||
|
aContent->GetAttr(kNameSpaceID_None,
|
||||||
|
nsAccessibilityAtoms::tooltiptext, textEquivalent);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendString(aString, textEquivalent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppendFromDOMChildren(aContent, aString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextEquivUtils::AppendString(nsAString *aString,
|
||||||
|
const nsAString& aTextEquivalent)
|
||||||
|
{
|
||||||
|
// Insert spaces to insure that words from controls aren't jammed together.
|
||||||
|
if (aTextEquivalent.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!aString->IsEmpty())
|
||||||
|
aString->Append(PRUnichar(' '));
|
||||||
|
|
||||||
|
aString->Append(aTextEquivalent);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name rules to role map.
|
||||||
|
|
||||||
|
PRUint32 nsTextEquivUtils::gRoleToNameRulesMap[] =
|
||||||
|
{
|
||||||
|
eNoRule, // ROLE_NOTHING
|
||||||
|
eNoRule, // ROLE_TITLEBAR
|
||||||
|
eNoRule, // ROLE_MENUBAR
|
||||||
|
eNoRule, // ROLE_SCROLLBAR
|
||||||
|
eNoRule, // ROLE_GRIP
|
||||||
|
eNoRule, // ROLE_SOUND
|
||||||
|
eNoRule, // ROLE_CURSOR
|
||||||
|
eNoRule, // ROLE_CARET
|
||||||
|
eNoRule, // ROLE_ALERT
|
||||||
|
eNoRule, // ROLE_WINDOW
|
||||||
|
eNoRule, // ROLE_INTERNAL_FRAME
|
||||||
|
eNoRule, // ROLE_MENUPOPUP
|
||||||
|
eFromSubtree, // ROLE_MENUITEM
|
||||||
|
eFromSubtree, // ROLE_TOOLTIP
|
||||||
|
eNoRule, // ROLE_APPLICATION
|
||||||
|
eNoRule, // ROLE_DOCUMENT
|
||||||
|
eNoRule, // ROLE_PANE
|
||||||
|
eNoRule, // ROLE_CHART
|
||||||
|
eNoRule, // ROLE_DIALOG
|
||||||
|
eNoRule, // ROLE_BORDER
|
||||||
|
eNoRule, // ROLE_GROUPING
|
||||||
|
eNoRule, // ROLE_SEPARATOR
|
||||||
|
eNoRule, // ROLE_TOOLBAR
|
||||||
|
eNoRule, // ROLE_STATUSBAR
|
||||||
|
eNoRule, // ROLE_TABLE
|
||||||
|
eFromSubtree, // ROLE_COLUMNHEADER
|
||||||
|
eFromSubtree, // ROLE_ROWHEADER
|
||||||
|
eFromSubtree, // ROLE_COLUMN
|
||||||
|
eFromSubtree, // ROLE_ROW
|
||||||
|
eFromSubtreeIfRec, // ROLE_CELL
|
||||||
|
eFromSubtree, // ROLE_LINK
|
||||||
|
eFromSubtree, // ROLE_HELPBALLOON
|
||||||
|
eNoRule, // ROLE_CHARACTER
|
||||||
|
eFromSubtreeIfRec, // ROLE_LIST
|
||||||
|
eFromSubtree, // ROLE_LISTITEM
|
||||||
|
eNoRule, // ROLE_OUTLINE
|
||||||
|
eFromSubtree, // ROLE_OUTLINEITEM
|
||||||
|
eFromSubtree, // ROLE_PAGETAB
|
||||||
|
eNoRule, // ROLE_PROPERTYPAGE
|
||||||
|
eNoRule, // ROLE_INDICATOR
|
||||||
|
eNoRule, // ROLE_GRAPHIC
|
||||||
|
eNoRule, // ROLE_STATICTEXT
|
||||||
|
eNoRule, // ROLE_TEXT_LEAF
|
||||||
|
eFromSubtree, // ROLE_PUSHBUTTON
|
||||||
|
eFromSubtree, // ROLE_CHECKBUTTON
|
||||||
|
eFromSubtree, // ROLE_RADIOBUTTON
|
||||||
|
eFromValue, // ROLE_COMBOBOX
|
||||||
|
eNoRule, // ROLE_DROPLIST
|
||||||
|
eFromValue, // ROLE_PROGRESSBAR
|
||||||
|
eNoRule, // ROLE_DIAL
|
||||||
|
eNoRule, // ROLE_HOTKEYFIELD
|
||||||
|
eNoRule, // ROLE_SLIDER
|
||||||
|
eNoRule, // ROLE_SPINBUTTON
|
||||||
|
eNoRule, // ROLE_DIAGRAM
|
||||||
|
eNoRule, // ROLE_ANIMATION
|
||||||
|
eNoRule, // ROLE_EQUATION
|
||||||
|
eFromSubtree, // ROLE_BUTTONDROPDOWN
|
||||||
|
eFromSubtree, // ROLE_BUTTONMENU
|
||||||
|
eFromSubtree, // ROLE_BUTTONDROPDOWNGRID
|
||||||
|
eNoRule, // ROLE_WHITESPACE
|
||||||
|
eNoRule, // ROLE_PAGETABLIST
|
||||||
|
eNoRule, // ROLE_CLOCK
|
||||||
|
eNoRule, // ROLE_SPLITBUTTON
|
||||||
|
eNoRule, // ROLE_IPADDRESS
|
||||||
|
eNoRule, // ROLE_ACCEL_LABEL
|
||||||
|
eNoRule, // ROLE_ARROW
|
||||||
|
eNoRule, // ROLE_CANVAS
|
||||||
|
eFromSubtree, // ROLE_CHECK_MENU_ITEM
|
||||||
|
eNoRule, // ROLE_COLOR_CHOOSER
|
||||||
|
eNoRule, // ROLE_DATE_EDITOR
|
||||||
|
eNoRule, // ROLE_DESKTOP_ICON
|
||||||
|
eNoRule, // ROLE_DESKTOP_FRAME
|
||||||
|
eNoRule, // ROLE_DIRECTORY_PANE
|
||||||
|
eNoRule, // ROLE_FILE_CHOOSER
|
||||||
|
eNoRule, // ROLE_FONT_CHOOSER
|
||||||
|
eNoRule, // ROLE_CHROME_WINDOW
|
||||||
|
eNoRule, // ROLE_GLASS_PANE
|
||||||
|
eFromSubtreeIfRec, // ROLE_HTML_CONTAINER
|
||||||
|
eNoRule, // ROLE_ICON
|
||||||
|
eFromSubtree, // ROLE_LABEL
|
||||||
|
eNoRule, // ROLE_LAYERED_PANE
|
||||||
|
eNoRule, // ROLE_OPTION_PANE
|
||||||
|
eNoRule, // ROLE_PASSWORD_TEXT
|
||||||
|
eNoRule, // ROLE_POPUP_MENU
|
||||||
|
eFromSubtree, // ROLE_RADIO_MENU_ITEM
|
||||||
|
eNoRule, // ROLE_ROOT_PANE
|
||||||
|
eNoRule, // ROLE_SCROLL_PANE
|
||||||
|
eNoRule, // ROLE_SPLIT_PANE
|
||||||
|
eFromSubtree, // ROLE_TABLE_COLUMN_HEADER
|
||||||
|
eFromSubtree, // ROLE_TABLE_ROW_HEADER
|
||||||
|
eFromSubtree, // ROLE_TEAR_OFF_MENU_ITEM
|
||||||
|
eNoRule, // ROLE_TERMINAL
|
||||||
|
eFromSubtreeIfRec, // ROLE_TEXT_CONTAINER
|
||||||
|
eFromSubtree, // ROLE_TOGGLE_BUTTON
|
||||||
|
eNoRule, // ROLE_TREE_TABLE
|
||||||
|
eNoRule, // ROLE_VIEWPORT
|
||||||
|
eNoRule, // ROLE_HEADER
|
||||||
|
eNoRule, // ROLE_FOOTER
|
||||||
|
eFromSubtreeIfRec, // ROLE_PARAGRAPH
|
||||||
|
eNoRule, // ROLE_RULER
|
||||||
|
eNoRule, // ROLE_AUTOCOMPLETE
|
||||||
|
eNoRule, // ROLE_EDITBAR
|
||||||
|
eFromValue, // ROLE_ENTRY
|
||||||
|
eNoRule, // ROLE_CAPTION
|
||||||
|
eNoRule, // ROLE_DOCUMENT_FRAME
|
||||||
|
eNoRule, // ROLE_HEADING
|
||||||
|
eNoRule, // ROLE_PAGE
|
||||||
|
eFromSubtreeIfRec, // ROLE_SECTION
|
||||||
|
eNoRule, // ROLE_REDUNDANT_OBJECT
|
||||||
|
eNoRule, // ROLE_FORM
|
||||||
|
eNoRule, // ROLE_IME
|
||||||
|
eNoRule, // ROLE_APP_ROOT
|
||||||
|
eFromSubtree, // ROLE_PARENT_MENUITEM
|
||||||
|
eNoRule, // ROLE_CALENDAR
|
||||||
|
eNoRule, // ROLE_COMBOBOX_LIST
|
||||||
|
eFromSubtree, // ROLE_COMBOBOX_OPTION
|
||||||
|
eNoRule, // ROLE_IMAGE_MAP
|
||||||
|
eFromSubtree, // ROLE_OPTION
|
||||||
|
eFromSubtree, // ROLE_RICH_OPTION
|
||||||
|
eNoRule, // ROLE_LISTBOX
|
||||||
|
eNoRule, // ROLE_FLAT_EQUATION
|
||||||
|
eFromSubtree // ROLE_GRID_CELL
|
||||||
|
};
|
|
@ -0,0 +1,168 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||||
|
*/
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef _nsTextEquivUtils_H_
|
||||||
|
#define _nsTextEquivUtils_H_
|
||||||
|
|
||||||
|
#include "nsIAccessible.h"
|
||||||
|
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsIStringBundle.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text equivalent computation rules (see nsTextEquivUtils::gRoleToNameRulesMap)
|
||||||
|
*/
|
||||||
|
enum ETextEquivRule
|
||||||
|
{
|
||||||
|
// No rule.
|
||||||
|
eNoRule = 0x00,
|
||||||
|
|
||||||
|
// Walk into subtree only if the currently navigated accessible is not root
|
||||||
|
// accessible (i.e. if the accessible is part of text equivalent computation).
|
||||||
|
eFromSubtreeIfRec = 0x01,
|
||||||
|
|
||||||
|
// Text equivalent computation from subtree is allowed.
|
||||||
|
eFromSubtree = 0x03,
|
||||||
|
|
||||||
|
// The accessible allows to append its value to text equivalent.
|
||||||
|
// XXX: This is temporary solution. Once we move accessible value of links
|
||||||
|
// and linkable accessibles to MSAA part we can remove this.
|
||||||
|
eFromValue = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class provides utils methods to compute the accessible name and
|
||||||
|
* description.
|
||||||
|
*/
|
||||||
|
class nsTextEquivUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the name from accessible subtree if allowed.
|
||||||
|
*
|
||||||
|
* @param aAccessible [in] the given accessible
|
||||||
|
* @param aName [out] accessible name
|
||||||
|
*/
|
||||||
|
static nsresult GetNameFromSubtree(nsIAccessible *aAccessible,
|
||||||
|
nsAString& aName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates text equivalent for the given accessible from its IDRefs
|
||||||
|
* attribute (like aria-labelledby or aria-describedby).
|
||||||
|
*
|
||||||
|
* @param aAccessible [in] the accessible text equivalent is computed for
|
||||||
|
* @param aIDRefsAttr [in] IDRefs attribute on DOM node of the accessible
|
||||||
|
* @param aTextEquiv [out] result text equivalent
|
||||||
|
*/
|
||||||
|
static nsresult GetTextEquivFromIDRefs(nsIAccessible *aAccessible,
|
||||||
|
nsIAtom *aIDRefsAttr,
|
||||||
|
nsAString& aTextEquiv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the text equivalent from the given content and its subtree if
|
||||||
|
* allowed and appends it to the given string.
|
||||||
|
*
|
||||||
|
* @param aInitiatorAcc [in] the accessible text equivalent is computed for
|
||||||
|
* in the end (root accessible of text equivalent
|
||||||
|
* calculation recursion)
|
||||||
|
* @param aContent [in] the given content the text equivalent is
|
||||||
|
* computed from
|
||||||
|
* @param aString [in, out] the string
|
||||||
|
*/
|
||||||
|
static nsresult AppendTextEquivFromContent(nsIAccessible *aInitiatorAcc,
|
||||||
|
nsIContent *aContent,
|
||||||
|
nsAString *aString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the text equivalent from the given text content (may be text
|
||||||
|
* node or html:br) and appends it to the given string.
|
||||||
|
*
|
||||||
|
* @param aContent [in] the text content
|
||||||
|
* @param aString [in, out] the string
|
||||||
|
*/
|
||||||
|
static nsresult AppendTextEquivFromTextContent(nsIContent *aContent,
|
||||||
|
nsAString *aString);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Iterates accessible children and calculates text equivalent from each
|
||||||
|
* child.
|
||||||
|
*/
|
||||||
|
static nsresult AppendFromAccessibleChildren(nsIAccessible *aAccessible,
|
||||||
|
nsAString *aString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates text equivalent from the given accessible and its subtree if
|
||||||
|
* allowed.
|
||||||
|
*/
|
||||||
|
static nsresult AppendFromAccessible(nsIAccessible *aAccessible,
|
||||||
|
nsAString *aString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates DOM children and calculates text equivalent from each child node.
|
||||||
|
*/
|
||||||
|
static nsresult AppendFromDOMChildren(nsIContent *aContent,
|
||||||
|
nsAString *aString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates text equivalent from the given DOM node and its subtree if
|
||||||
|
* allowed.
|
||||||
|
*/
|
||||||
|
static nsresult AppendFromDOMNode(nsIContent *aContent, nsAString *aString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenates strings and appends space between them.
|
||||||
|
*/
|
||||||
|
static void AppendString(nsAString *aString, const nsAString& aTextEquivalent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map array from roles to name rules (constants of ETextEquivRule).
|
||||||
|
*/
|
||||||
|
static PRUint32 gRoleToNameRulesMap[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accessible for which we are computing a text equivalent. It is useful
|
||||||
|
* for bailing out during recursive text computation, or for special cases
|
||||||
|
* like step f. of the ARIA implementation guide.
|
||||||
|
*/
|
||||||
|
static nsCOMPtr<nsIAccessible> gInitiatorAcc;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -627,7 +627,8 @@ nsHTMLGroupboxAccessible::GetNameInternal(nsAString& aName)
|
||||||
|
|
||||||
nsIContent *legendContent = GetLegend();
|
nsIContent *legendContent = GetLegend();
|
||||||
if (legendContent) {
|
if (legendContent) {
|
||||||
return AppendFlatStringFromSubtree(legendContent, &aName);
|
return nsTextEquivUtils::
|
||||||
|
AppendTextEquivFromContent(this, legendContent, &aName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -526,7 +526,8 @@ nsHTMLSelectOptionAccessible::GetNameInternal(nsAString& aName)
|
||||||
|
|
||||||
if (text->IsNodeOfType(nsINode::eTEXT)) {
|
if (text->IsNodeOfType(nsINode::eTEXT)) {
|
||||||
nsAutoString txtValue;
|
nsAutoString txtValue;
|
||||||
nsresult rv = AppendFlatStringFromContentNode(text, &txtValue);
|
nsresult rv = nsTextEquivUtils::
|
||||||
|
AppendTextEquivFromTextContent(text, &txtValue);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// Temp var (txtValue) needed until CompressWhitespace built for nsAString
|
// Temp var (txtValue) needed until CompressWhitespace built for nsAString
|
||||||
|
|
|
@ -967,7 +967,8 @@ NS_IMETHODIMP nsHTMLTableAccessible::GetDescription(nsAString& aDescription)
|
||||||
captionAccessNode->GetDOMNode(getter_AddRefs(captionNode));
|
captionAccessNode->GetDOMNode(getter_AddRefs(captionNode));
|
||||||
nsCOMPtr<nsIContent> captionContent = do_QueryInterface(captionNode);
|
nsCOMPtr<nsIContent> captionContent = do_QueryInterface(captionNode);
|
||||||
if (captionContent) {
|
if (captionContent) {
|
||||||
AppendFlatStringFromSubtree(captionContent, &aDescription);
|
nsTextEquivUtils::
|
||||||
|
AppendTextEquivFromContent(this, captionContent, &aDescription);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef SHOW_LAYOUT_HEURISTIC
|
#ifdef SHOW_LAYOUT_HEURISTIC
|
||||||
|
|
|
@ -169,22 +169,9 @@ nsTextAccessible(aDomNode, aShell)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTMLLabelAccessible::GetNameInternal(nsAString& aReturn)
|
nsHTMLLabelAccessible::GetNameInternal(nsAString& aName)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
return nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
|
||||||
|
|
||||||
nsAutoString name;
|
|
||||||
if (content)
|
|
||||||
rv = AppendFlatStringFromSubtree(content, &name);
|
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
// Temp var needed until CompressWhitespace built for nsAString
|
|
||||||
name.CompressWhitespace();
|
|
||||||
aReturn = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsHTMLLabelAccessible::GetRole(PRUint32 *aRole)
|
NS_IMETHODIMP nsHTMLLabelAccessible::GetRole(PRUint32 *aRole)
|
||||||
|
|
|
@ -234,7 +234,9 @@ NS_IMETHODIMP
|
||||||
nsXFormsAccessible::GetDescription(nsAString& aDescription)
|
nsXFormsAccessible::GetDescription(nsAString& aDescription)
|
||||||
{
|
{
|
||||||
nsAutoString description;
|
nsAutoString description;
|
||||||
nsresult rv = GetTextFromRelationID(nsAccessibilityAtoms::aria_describedby, description);
|
nsresult rv = nsTextEquivUtils::
|
||||||
|
GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_describedby,
|
||||||
|
description);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && !description.IsEmpty()) {
|
if (NS_SUCCEEDED(rv) && !description.IsEmpty()) {
|
||||||
aDescription = description;
|
aDescription = description;
|
||||||
|
|
|
@ -66,7 +66,9 @@ NS_IMETHODIMP
|
||||||
nsXFormsLabelAccessible::GetDescription(nsAString& aDescription)
|
nsXFormsLabelAccessible::GetDescription(nsAString& aDescription)
|
||||||
{
|
{
|
||||||
nsAutoString description;
|
nsAutoString description;
|
||||||
nsresult rv = GetTextFromRelationID(nsAccessibilityAtoms::aria_describedby, description);
|
nsresult rv = nsTextEquivUtils::
|
||||||
|
GetTextEquivFromIDRefs(this, nsAccessibilityAtoms::aria_describedby,
|
||||||
|
description);
|
||||||
aDescription = description;
|
aDescription = description;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsresult ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
|
nsresult ChangeSelection(PRInt32 aIndex, PRUint8 aMethod, PRBool *aSelState);
|
||||||
nsresult AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString)
|
|
||||||
{ return NS_OK; } // Overrides base impl in nsAccessible
|
|
||||||
|
|
||||||
// nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
|
// nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
|
||||||
// one of these if the widget is valid and not defunct
|
// one of these if the widget is valid and not defunct
|
||||||
|
|
|
@ -165,12 +165,15 @@ nsXULLinkAccessible::GetValue(nsAString& aValue)
|
||||||
nsresult
|
nsresult
|
||||||
nsXULLinkAccessible::GetNameInternal(nsAString& aName)
|
nsXULLinkAccessible::GetNameInternal(nsAString& aName)
|
||||||
{
|
{
|
||||||
|
if (IsDefunct())
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||||
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
|
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
|
||||||
if (!aName.IsEmpty())
|
if (!aName.IsEmpty())
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
return AppendFlatStringFromSubtree(content, &aName);
|
return nsTextEquivUtils::GetNameFromSubtree(this, aName);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -81,7 +81,7 @@ _TEST_FILES =\
|
||||||
test_nsIAccessible_name.html \
|
test_nsIAccessible_name.html \
|
||||||
test_nsIAccessible_name_button.html \
|
test_nsIAccessible_name_button.html \
|
||||||
test_nsIAccessible_name_link.html \
|
test_nsIAccessible_name_link.html \
|
||||||
$(warning test_nsIAccessible_name.xul temporarily disabled) \
|
test_nsIAccessible_name.xul \
|
||||||
test_nsIAccessible_selects.html \
|
test_nsIAccessible_selects.html \
|
||||||
test_nsIAccessible_focus.html \
|
test_nsIAccessible_focus.html \
|
||||||
test_nsIAccessibleDocument.html \
|
test_nsIAccessibleDocument.html \
|
||||||
|
|
|
@ -178,6 +178,9 @@ function getNode(aNodeOrID)
|
||||||
*/
|
*/
|
||||||
function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIfNoAcc)
|
function getAccessible(aAccOrElmOrID, aInterfaces, aElmObj, aDoNotFailIfNoAcc)
|
||||||
{
|
{
|
||||||
|
if (!aAccOrElmOrID)
|
||||||
|
return;
|
||||||
|
|
||||||
var elm = null;
|
var elm = null;
|
||||||
|
|
||||||
if (aAccOrElmOrID instanceof nsIAccessible) {
|
if (aAccOrElmOrID instanceof nsIAccessible) {
|
||||||
|
@ -246,6 +249,27 @@ function isAccessible(aAccOrElmOrID)
|
||||||
return getAccessible(aAccOrElmOrID, null, null, true) ? true : false;
|
return getAccessible(aAccOrElmOrID, null, null, true) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run through accessible tree of the given identifier so that we ensure
|
||||||
|
* accessible tree is created.
|
||||||
|
*/
|
||||||
|
function ensureAccessibleTree(aAccOrElmOrID)
|
||||||
|
{
|
||||||
|
var acc = getAccessible(aAccOrElmOrID);
|
||||||
|
if (!acc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var child = acc.firstChild;
|
||||||
|
while (child) {
|
||||||
|
ensureAccessibleTree(child);
|
||||||
|
try {
|
||||||
|
child = child.nextSibling;
|
||||||
|
} catch (e) {
|
||||||
|
child = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert role to human readable string.
|
* Convert role to human readable string.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constants
|
||||||
|
|
||||||
|
const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
|
||||||
|
const EVENT_DOM_DESTROY = nsIAccessibleEvent.EVENT_DOM_DESTROY;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// General
|
// General
|
||||||
|
|
||||||
|
@ -6,6 +12,38 @@
|
||||||
*/
|
*/
|
||||||
var gA11yEventDumpID = "";
|
var gA11yEventDumpID = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the function when requested event is handled.
|
||||||
|
*
|
||||||
|
* @param aEventType [in] event type
|
||||||
|
* @param aTarget [in] event target
|
||||||
|
* @param aFunc [in] function to call when event is handled
|
||||||
|
* @param aContext [in, optional] object in which context the function is
|
||||||
|
* called
|
||||||
|
* @param aArg1 [in, optional] argument passed into the function
|
||||||
|
* @param aArg2 [in, optional] argument passed into the function
|
||||||
|
*/
|
||||||
|
function waitForEvent(aEventType, aTarget, aFunc, aContext, aArg1, aArg2)
|
||||||
|
{
|
||||||
|
var handler = {
|
||||||
|
handleEvent: function handleEvent(aEvent) {
|
||||||
|
if (!aTarget || aTarget == aEvent.DOMNode) {
|
||||||
|
unregisterA11yEventListener(aEventType, this);
|
||||||
|
|
||||||
|
window.setTimeout(
|
||||||
|
function ()
|
||||||
|
{
|
||||||
|
aFunc.call(aContext, aArg1, aArg2);
|
||||||
|
},
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
registerA11yEventListener(aEventType, handler);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register accessibility event listener.
|
* Register accessibility event listener.
|
||||||
*
|
*
|
||||||
|
@ -386,6 +424,9 @@ function removeA11yEventListener(aEventType, aEventHandler)
|
||||||
|
|
||||||
function dumpInfoToDOM(aInfo)
|
function dumpInfoToDOM(aInfo)
|
||||||
{
|
{
|
||||||
|
if (!gA11yEventDumpID)
|
||||||
|
return;
|
||||||
|
|
||||||
var dumpElm = document.getElementById(gA11yEventDumpID);
|
var dumpElm = document.getElementById(gA11yEventDumpID);
|
||||||
var div = document.createElement("div");
|
var div = document.createElement("div");
|
||||||
div.textContent = aInfo;
|
div.textContent = aInfo;
|
||||||
|
|
|
@ -119,6 +119,7 @@
|
||||||
<rule fromsubtree="true"/>
|
<rule fromsubtree="true"/>
|
||||||
<rule attr="title" type="string"/>
|
<rule attr="title" type="string"/>
|
||||||
</ruleset>
|
</ruleset>
|
||||||
|
|
||||||
</ruledfn>
|
</ruledfn>
|
||||||
|
|
||||||
<rulesample>
|
<rulesample>
|
||||||
|
@ -193,12 +194,13 @@
|
||||||
role="gridcell"
|
role="gridcell"
|
||||||
aria-label="test1"
|
aria-label="test1"
|
||||||
aria-labelledby="l1 l2"
|
aria-labelledby="l1 l2"
|
||||||
a11yname=" This is a paragraph This is a link This is a list"
|
a11yname="This is a paragraph This is a link • Listitem1 • Listitem2"
|
||||||
title="This is a paragraph This is a link This is a list">
|
title="This is a paragraph This is a link This is a list">
|
||||||
<html:p>This is a paragraph</html:p>
|
<html:p>This is a paragraph</html:p>
|
||||||
<html:a href="#">This is a link</html:a>
|
<html:a href="#">This is a link</html:a>
|
||||||
<html:ul>
|
<html:ul>
|
||||||
<html:li>This is a list</html:li>
|
<html:li>Listitem1</html:li>
|
||||||
|
<html:li>Listitem2</html:li>
|
||||||
</html:ul>
|
</html:ul>
|
||||||
</html:td>
|
</html:td>
|
||||||
</html:tr>
|
</html:tr>
|
||||||
|
|
|
@ -3,9 +3,8 @@ function testName(aAccOrElmOrID, aName, aMsg)
|
||||||
var msg = aMsg ? aMsg : "";
|
var msg = aMsg ? aMsg : "";
|
||||||
|
|
||||||
var acc = getAccessible(aAccOrElmOrID);
|
var acc = getAccessible(aAccOrElmOrID);
|
||||||
if (!acc) {
|
if (!acc)
|
||||||
ok(false, msg + "No accessible for " + aAccOrElmOrID + "!");
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
is(acc.name, aName, msg + "Wrong name of the accessible for " + aAccOrElmOrID);
|
is(acc.name, aName, msg + "Wrong name of the accessible for " + aAccOrElmOrID);
|
||||||
|
@ -36,13 +35,67 @@ function testNames()
|
||||||
gRuleDoc = request.responseXML;
|
gRuleDoc = request.responseXML;
|
||||||
|
|
||||||
var markupElms = evaluateXPath(gRuleDoc, "//rules/rulesample/markup");
|
var markupElms = evaluateXPath(gRuleDoc, "//rules/rulesample/markup");
|
||||||
for (var idx = 0; idx < markupElms.length; idx++)
|
gTestIterator.iterateMarkups(markupElms);
|
||||||
testNamesForMarkup(markupElms[idx]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Private section.
|
// Private section.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to interate through name tests.
|
||||||
|
*/
|
||||||
|
var gTestIterator =
|
||||||
|
{
|
||||||
|
iterateMarkups: function gTestIterator_iterateMarkups(aMarkupElms)
|
||||||
|
{
|
||||||
|
this.markupElms = aMarkupElms;
|
||||||
|
|
||||||
|
this.iterateNext();
|
||||||
|
},
|
||||||
|
|
||||||
|
iterateRules: function gTestIterator_iterateRules(aElm, aContainer, aRuleElms)
|
||||||
|
{
|
||||||
|
this.ruleElms = aRuleElms;
|
||||||
|
this.elm = aElm;
|
||||||
|
this.container = aContainer;
|
||||||
|
|
||||||
|
this.iterateNext();
|
||||||
|
},
|
||||||
|
|
||||||
|
iterateNext: function gTestIterator_iterateNext()
|
||||||
|
{
|
||||||
|
if (this.markupIdx == -1) {
|
||||||
|
this.markupIdx++;
|
||||||
|
testNamesForMarkup(this.markupElms[this.markupIdx]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ruleIdx++;
|
||||||
|
if (this.ruleIdx == this.ruleElms.length) {
|
||||||
|
this.markupIdx++;
|
||||||
|
if (this.markupIdx == this.markupElms.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(this.container);
|
||||||
|
|
||||||
|
this.ruleIdx = -1;
|
||||||
|
testNamesForMarkup(this.markupElms[this.markupIdx]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
testNameForRule(this.elm, this.ruleElms[this.ruleIdx]);
|
||||||
|
},
|
||||||
|
|
||||||
|
markupElms: null,
|
||||||
|
markupIdx: -1,
|
||||||
|
ruleElms: null,
|
||||||
|
ruleIdx: -1,
|
||||||
|
elm: null,
|
||||||
|
container: null
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process every 'markup' element and test names for it. Used by testNames
|
* Process every 'markup' element and test names for it. Used by testNames
|
||||||
* function.
|
* function.
|
||||||
|
@ -50,7 +103,7 @@ function testNames()
|
||||||
function testNamesForMarkup(aMarkupElm)
|
function testNamesForMarkup(aMarkupElm)
|
||||||
{
|
{
|
||||||
var div = document.createElement("div");
|
var div = document.createElement("div");
|
||||||
div.setAttribute("test", "test");
|
div.setAttribute("id", "test");
|
||||||
|
|
||||||
var child = aMarkupElm.firstChild;
|
var child = aMarkupElm.firstChild;
|
||||||
while (child) {
|
while (child) {
|
||||||
|
@ -58,90 +111,114 @@ function testNamesForMarkup(aMarkupElm)
|
||||||
div.appendChild(newChild);
|
div.appendChild(newChild);
|
||||||
child = child.nextSibling;
|
child = child.nextSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waitForEvent(EVENT_REORDER, document, testNamesForMarkupRules,
|
||||||
|
null, aMarkupElm, div);
|
||||||
|
|
||||||
document.body.appendChild(div);
|
document.body.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNamesForMarkupRules(aMarkupElm, aContainer)
|
||||||
|
{
|
||||||
|
ensureAccessibleTree(aContainer);
|
||||||
|
|
||||||
var serializer = new XMLSerializer();
|
var serializer = new XMLSerializer();
|
||||||
|
|
||||||
var expr = "//html/body/div[@test='test']/" + aMarkupElm.getAttribute("ref");
|
var expr = "//html/body/div[@id='test']/" + aMarkupElm.getAttribute("ref");
|
||||||
var elms = evaluateXPath(document, expr, htmlDocResolver);
|
var elms = evaluateXPath(document, expr, htmlDocResolver);
|
||||||
|
|
||||||
var ruleId = aMarkupElm.getAttribute("ruleset");
|
var ruleId = aMarkupElm.getAttribute("ruleset");
|
||||||
var ruleElms = getRuleElmsByRulesetId(ruleId);
|
var ruleElms = getRuleElmsByRulesetId(ruleId);
|
||||||
|
|
||||||
for (var idx = 0; idx < ruleElms.length; idx++)
|
gTestIterator.iterateRules(elms[0], aContainer, ruleElms);
|
||||||
testNameForRule(elms[0], ruleElms[idx]);
|
|
||||||
|
|
||||||
document.body.removeChild(div);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test name for current rule and current 'markup' element. Used by
|
* Test name for current rule and current 'markup' element. Used by
|
||||||
* testNamesForMarkup function.
|
* testNamesForMarkup function.
|
||||||
*/
|
*/
|
||||||
function testNameForRule(aElm, aRule)
|
function testNameForRule(aElm, aRuleElm)
|
||||||
{
|
{
|
||||||
|
if (aRuleElm.hasAttribute("attr"))
|
||||||
|
testNameForAttrRule(aElm, aRuleElm);
|
||||||
|
else if (aRuleElm.hasAttribute("elm") && aRuleElm.hasAttribute("elmattr"))
|
||||||
|
testNameForElmRule(aElm, aRuleElm);
|
||||||
|
else if (aRuleElm.getAttribute("fromsubtree") == "true")
|
||||||
|
testNameForSubtreeRule(aElm, aRuleElm);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNameForAttrRule(aElm, aRule)
|
||||||
|
{
|
||||||
|
var name = "";
|
||||||
|
|
||||||
var attr = aRule.getAttribute("attr");
|
var attr = aRule.getAttribute("attr");
|
||||||
if (attr) {
|
var attrValue = aElm.getAttribute(attr);
|
||||||
var name = "";
|
|
||||||
var attrValue = aElm.getAttribute(attr);
|
|
||||||
|
|
||||||
var type = aRule.getAttribute("type");
|
var type = aRule.getAttribute("type");
|
||||||
if (type == "string") {
|
if (type == "string") {
|
||||||
name = attrValue;
|
name = attrValue;
|
||||||
|
|
||||||
} else if (type == "ref") {
|
} else if (type == "ref") {
|
||||||
var ids = attrValue.split(/\s+/);///\,\s*/);
|
var ids = attrValue.split(/\s+/);
|
||||||
for (var idx = 0; idx < ids.length; idx++) {
|
for (var idx = 0; idx < ids.length; idx++) {
|
||||||
var labelElm = getNode(ids[idx]);
|
var labelElm = getNode(ids[idx]);
|
||||||
if (name != "")
|
if (name != "")
|
||||||
name += " ";
|
name += " ";
|
||||||
|
|
||||||
name += labelElm.getAttribute("a11yname");
|
name += labelElm.getAttribute("a11yname");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = "Attribute '" + attr + "' test. ";
|
|
||||||
testName(aElm, name, msg);
|
|
||||||
aElm.removeAttribute(attr);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var msg = "Attribute '" + attr + "' test. ";
|
||||||
|
testName(aElm, name, msg);
|
||||||
|
aElm.removeAttribute(attr);
|
||||||
|
|
||||||
|
gTestIterator.iterateNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNameForElmRule(aElm, aRule)
|
||||||
|
{
|
||||||
var elm = aRule.getAttribute("elm");
|
var elm = aRule.getAttribute("elm");
|
||||||
var elmattr = aRule.getAttribute("elmattr");
|
var elmattr = aRule.getAttribute("elmattr");
|
||||||
if (elm && elmattr) {
|
|
||||||
var filter = {
|
|
||||||
acceptNode: function filter_acceptNode(aNode)
|
|
||||||
{
|
|
||||||
if (aNode.localName == this.mLocalName &&
|
|
||||||
aNode.getAttribute(this.mAttrName) == this.mAttrValue)
|
|
||||||
return NodeFilter.FILTER_ACCEPT;
|
|
||||||
|
|
||||||
return NodeFilter.FILTER_SKIP;
|
var filter = {
|
||||||
},
|
acceptNode: function filter_acceptNode(aNode)
|
||||||
|
{
|
||||||
|
if (aNode.localName == this.mLocalName &&
|
||||||
|
aNode.getAttribute(this.mAttrName) == this.mAttrValue)
|
||||||
|
return NodeFilter.FILTER_ACCEPT;
|
||||||
|
|
||||||
mLocalName: elm,
|
return NodeFilter.FILTER_SKIP;
|
||||||
mAttrName: elmattr,
|
},
|
||||||
mAttrValue: aElm.getAttribute("id")
|
|
||||||
};
|
|
||||||
|
|
||||||
var treeWalker = document.createTreeWalker(document.body,
|
mLocalName: elm,
|
||||||
NodeFilter.SHOW_ELEMENT,
|
mAttrName: elmattr,
|
||||||
filter, false);
|
mAttrValue: aElm.getAttribute("id")
|
||||||
var labelElm = treeWalker.nextNode();
|
};
|
||||||
var msg = "Element '" + elm + "' test.";
|
|
||||||
testName(aElm, labelElm.getAttribute("a11yname"), msg);
|
|
||||||
labelElm.parentNode.removeChild(labelElm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fromSubtree = aRule.getAttribute("fromsubtree");
|
var treeWalker = document.createTreeWalker(document.body,
|
||||||
if (fromSubtree == "true") {
|
NodeFilter.SHOW_ELEMENT,
|
||||||
var msg = "From subtree test.";
|
filter, false);
|
||||||
testName(aElm, aElm.getAttribute("a11yname"), msg);
|
var labelElm = treeWalker.nextNode();
|
||||||
while (aElm.firstChild)
|
var msg = "Element '" + elm + "' test.";
|
||||||
aElm.removeChild(aElm.firstChild);
|
testName(aElm, labelElm.getAttribute("a11yname"), msg);
|
||||||
return;
|
|
||||||
}
|
var parentNode = labelElm.parentNode;
|
||||||
|
waitForEvent(EVENT_REORDER, parentNode,
|
||||||
|
gTestIterator.iterateNext, gTestIterator);
|
||||||
|
|
||||||
|
parentNode.removeChild(labelElm);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNameForSubtreeRule(aElm, aRule)
|
||||||
|
{
|
||||||
|
var msg = "From subtree test.";
|
||||||
|
testName(aElm, aElm.getAttribute("a11yname"), msg);
|
||||||
|
|
||||||
|
waitForEvent(EVENT_REORDER, aElm, gTestIterator.iterateNext, gTestIterator);
|
||||||
|
|
||||||
|
while (aElm.firstChild)
|
||||||
|
aElm.removeChild(aElm.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>nsIAccessible::name calculation for HTML buttons</title>
|
<title>nsIAccessible::name calculation for elements</title>
|
||||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||||
|
|
||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
|
@ -10,19 +10,16 @@
|
||||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
|
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/a11y/accessible/events.js"></script>
|
||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="chrome://mochikit/content/a11y/accessible/nsIAccessible_name.js"></script>
|
src="chrome://mochikit/content/a11y/accessible/nsIAccessible_name.js"></script>
|
||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
function doTest()
|
// gA11yEventDumpID = "eventdump";
|
||||||
{
|
|
||||||
testNames();
|
|
||||||
|
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
addLoadEvent(doTest);
|
addA11yLoadEvent(testNames);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
@ -31,7 +28,7 @@
|
||||||
|
|
||||||
<a target="_blank"
|
<a target="_blank"
|
||||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=459635"
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=459635"
|
||||||
title="nsIAccessible::name calculation for HTML buttons">
|
title="nsIAccessible::name calculation for elements">
|
||||||
Mozilla Bug 459635
|
Mozilla Bug 459635
|
||||||
</a>
|
</a>
|
||||||
<p id="display"></p>
|
<p id="display"></p>
|
||||||
|
@ -39,6 +36,6 @@
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<div id="eventdump"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -35,6 +35,10 @@
|
||||||
// of elements. Gets the name from text nodes of those elements.
|
// of elements. Gets the name from text nodes of those elements.
|
||||||
testName("btn_labelledby_texts", "text1 text2");
|
testName("btn_labelledby_texts", "text1 text2");
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name from named accessible
|
||||||
|
|
||||||
|
testName("input_labelledby_namedacc", "Data");
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Name from subtree (single relation labelled_by).
|
// Name from subtree (single relation labelled_by).
|
||||||
|
@ -129,9 +133,20 @@
|
||||||
testName("textareawithchild", "Story: Bar");
|
testName("textareawithchild", "Story: Bar");
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// label with nested combobox
|
// label with nested combobox (test for 'f' item of name computation guide)
|
||||||
|
|
||||||
|
testName("comboinstart", "One day(s).");
|
||||||
|
testName("combo3", "day(s).");
|
||||||
|
|
||||||
testName("comboinmiddle", "Subscribe to ATOM feed.");
|
testName("comboinmiddle", "Subscribe to ATOM feed.");
|
||||||
|
testName("combo4", "Subscribe to ATOM feed.");
|
||||||
|
|
||||||
|
testName("comboinmiddle2", "Play the Haliluya sound when new mail arrives");
|
||||||
|
testName("combo5", "Play the Haliluya sound when new mail arrives");
|
||||||
|
testName("checkbox", "Play the Haliluya sound when new mail arrives");
|
||||||
|
|
||||||
|
testName("comboinend", "This day was sunny");
|
||||||
|
testName("combo6", "This day was");
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
@ -175,6 +190,12 @@
|
||||||
aria-labelledby="labelledby_text1 labelledby_text2">2</button>
|
aria-labelledby="labelledby_text1 labelledby_text2">2</button>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
<!-- name from named accessible -->
|
||||||
|
<input id="labelledby_namedacc" type="checkbox"
|
||||||
|
aria-label="Data" />
|
||||||
|
<input id="input_labelledby_namedacc"
|
||||||
|
aria-labelledby="labelledby_namedacc" />
|
||||||
|
|
||||||
<!-- the name from subtree, mixed content -->
|
<!-- the name from subtree, mixed content -->
|
||||||
<span id="labelledby_mixed">no<span>more text</span></span>
|
<span id="labelledby_mixed">no<span>more text</span></span>
|
||||||
<button id="btn_labelledby_mixed"
|
<button id="btn_labelledby_mixed"
|
||||||
|
@ -286,16 +307,39 @@
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- A label with a nested control in the middle -->
|
<!-- a label with a nested control in the start, middle and end -->
|
||||||
<form>
|
<form>
|
||||||
|
<label id="comboinstart"><select id="combo3">
|
||||||
|
<option>One</option>
|
||||||
|
<option>Two</option>
|
||||||
|
</select>
|
||||||
|
day(s).
|
||||||
|
</label>
|
||||||
|
|
||||||
<label id="comboinmiddle">
|
<label id="comboinmiddle">
|
||||||
Subscribe to
|
Subscribe to
|
||||||
<select id="combo3" name="occupation">
|
<select id="combo4" name="occupation">
|
||||||
<option>ATOM</option>
|
<option>ATOM</option>
|
||||||
<option>RSS</option>
|
<option>RSS</option>
|
||||||
</select>
|
</select>
|
||||||
feed.
|
feed.
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<label id="comboinmiddle2" for="checkbox">Play the
|
||||||
|
<select id="combo5">
|
||||||
|
<option>Haliluya</option>
|
||||||
|
<option>Hurra</option>
|
||||||
|
</select>
|
||||||
|
sound when new mail arrives
|
||||||
|
</label>
|
||||||
|
<input id="checkbox" type="checkbox" />
|
||||||
|
|
||||||
|
<label id="comboinend">
|
||||||
|
This day was
|
||||||
|
<select id="combo6" name="occupation">
|
||||||
|
<option>sunny</option>
|
||||||
|
<option>rainy</option>
|
||||||
|
</select></label>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -40,6 +40,10 @@
|
||||||
// of elements. Gets the name from text nodes of those elements.
|
// of elements. Gets the name from text nodes of those elements.
|
||||||
testName("btn_labelledby_texts", "text1 text2");
|
testName("btn_labelledby_texts", "text1 text2");
|
||||||
|
|
||||||
|
// Trick cases. Self and recursive referencing.
|
||||||
|
testName("rememberHistoryDays", "Remember 3 days");
|
||||||
|
testName("historyDays", "Remember 3 days");
|
||||||
|
testName("rememberAfter", null); // XUL labels doesn't allow name from subtree
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Name from subtree (single relation labelled_by).
|
// Name from subtree (single relation labelled_by).
|
||||||
|
@ -101,7 +105,7 @@
|
||||||
// Get the name from anonymous label element for anonymous textbox
|
// Get the name from anonymous label element for anonymous textbox
|
||||||
// (@anonid is used).
|
// (@anonid is used).
|
||||||
var ID = "box_label_anon1";
|
var ID = "box_label_anon1";
|
||||||
var box1Acc = testName(ID, "");
|
var box1Acc = testName(ID, null);
|
||||||
if (box1Acc) {
|
if (box1Acc) {
|
||||||
var textboxAcc = box1Acc.firstChild;
|
var textboxAcc = box1Acc.firstChild;
|
||||||
is(textboxAcc.name, "Label",
|
is(textboxAcc.name, "Label",
|
||||||
|
@ -111,7 +115,7 @@
|
||||||
// Get the name from anonymous label element for anonymous textbox
|
// Get the name from anonymous label element for anonymous textbox
|
||||||
// (@anonid is used). Nested bindings.
|
// (@anonid is used). Nested bindings.
|
||||||
ID = "box_label_anon2";
|
ID = "box_label_anon2";
|
||||||
var box2Acc = testName(ID, "");
|
var box2Acc = testName(ID, null);
|
||||||
if (box2Acc) {
|
if (box2Acc) {
|
||||||
var textboxAcc = box2Acc.firstChild;
|
var textboxAcc = box2Acc.firstChild;
|
||||||
is(textboxAcc.name, "Label",
|
is(textboxAcc.name, "Label",
|
||||||
|
@ -195,6 +199,14 @@
|
||||||
<button id="btn_labelledby_texts"
|
<button id="btn_labelledby_texts"
|
||||||
aria-labelledby="labelledby_text1 labelledby_text2"/>
|
aria-labelledby="labelledby_text1 labelledby_text2"/>
|
||||||
|
|
||||||
|
<!-- trick aria-labelledby -->
|
||||||
|
<checkbox id="rememberHistoryDays"
|
||||||
|
label="Remember "
|
||||||
|
aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
|
||||||
|
<textbox id="historyDays" type="number" size="3" value="3"
|
||||||
|
aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
|
||||||
|
<label id="rememberAfter">days</label>
|
||||||
|
|
||||||
<!-- the name from subtree, mixed content -->
|
<!-- the name from subtree, mixed content -->
|
||||||
<description id="labelledby_mixed">
|
<description id="labelledby_mixed">
|
||||||
no<description>more text</description>
|
no<description>more text</description>
|
||||||
|
|
|
@ -47,8 +47,8 @@
|
||||||
names = [
|
names = [
|
||||||
"Search in: Newsticker", // label
|
"Search in: Newsticker", // label
|
||||||
"Search in:", // text leaf
|
"Search in:", // text leaf
|
||||||
"Search in: Newsticker", // combobox
|
"Search in:", // combobox
|
||||||
"Search in:", // combobox_list
|
"Search in: Newsticker", // combobox_list
|
||||||
"Newsticker", // option 1
|
"Newsticker", // option 1
|
||||||
"Entire site" // Option 2
|
"Entire site" // Option 2
|
||||||
];
|
];
|
||||||
|
|
|
@ -24,8 +24,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=475006
|
||||||
testAttrs("autocomplete", {"autocomplete" : "true"}, true);
|
testAttrs("autocomplete", {"autocomplete" : "true"}, true);
|
||||||
// bug 477876 testAttrs("checked", {"checkable" : "true"}, true);
|
// bug 477876 testAttrs("checked", {"checkable" : "true"}, true);
|
||||||
testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
|
testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
|
||||||
|
|
||||||
|
// live object attribute
|
||||||
testAttrs("live", {"live" : "polite"}, true);
|
testAttrs("live", {"live" : "polite"}, true);
|
||||||
testAttrs("me", {"container-live" : "polite"}, true);
|
testAttrs("live2", {"live" : "polite"}, true);
|
||||||
|
testAttrs("log", {"live" : "polite"}, true);
|
||||||
|
testAttrs("marquee", {"live" : "off"}, true);
|
||||||
|
testAttrs("status", {"live" : "polite"}, true);
|
||||||
|
testAttrs("timer", {"live" : "off"}, true);
|
||||||
|
|
||||||
|
// container-live object attribute
|
||||||
|
testAttrs("liveChild", {"container-live" : "polite"}, true);
|
||||||
|
testAttrs("live2Child", {"container-live" : "polite"}, true);
|
||||||
|
testAttrs("logChild", {"container-live" : "polite"}, true);
|
||||||
|
testAttrs("marqueeChild", {"container-live" : "off"}, true);
|
||||||
|
testAttrs("statusChild", {"container-live" : "polite"}, true);
|
||||||
|
testAttrs("timerChild", {"container-live" : "off"}, true);
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
@ -50,7 +64,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=475006
|
||||||
<div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
|
<div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
|
||||||
<div id="checked" aria-checked="true"></div>
|
<div id="checked" aria-checked="true"></div>
|
||||||
<div id="dropeffect" aria-dropeffect="copy"></div>
|
<div id="dropeffect" aria-dropeffect="copy"></div>
|
||||||
<div id="live" aria-live="polite">excuse <div id="me">me</div></div>
|
|
||||||
|
<div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
|
||||||
|
<div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
|
||||||
|
<div id="log" role="log">excuse <div id="logChild">me</div></div>
|
||||||
|
<div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>
|
||||||
|
<div id="status" role="status">excuse <div id="statusChild">me</div></div>
|
||||||
|
<div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4909,7 +4909,7 @@ var contentAreaDNDObserver = {
|
||||||
|
|
||||||
var dragType = aXferData.flavour.contentType;
|
var dragType = aXferData.flavour.contentType;
|
||||||
var dragData = aXferData.data;
|
var dragData = aXferData.data;
|
||||||
if (dragType == "application/x-moz-tabbrowser-tab") {
|
if (dragType == TAB_DROP_TYPE) {
|
||||||
// If the tab was dragged from some other tab bar, its own dragend
|
// If the tab was dragged from some other tab bar, its own dragend
|
||||||
// handler will take care of detaching the tab
|
// handler will take care of detaching the tab
|
||||||
if (dragData instanceof XULElement && dragData.localName == "tab" &&
|
if (dragData instanceof XULElement && dragData.localName == "tab" &&
|
||||||
|
@ -4958,7 +4958,7 @@ var contentAreaDNDObserver = {
|
||||||
getSupportedFlavours: function ()
|
getSupportedFlavours: function ()
|
||||||
{
|
{
|
||||||
var flavourSet = new FlavourSet();
|
var flavourSet = new FlavourSet();
|
||||||
flavourSet.appendFlavour("application/x-moz-tabbrowser-tab");
|
flavourSet.appendFlavour(TAB_DROP_TYPE);
|
||||||
flavourSet.appendFlavour("text/x-moz-url");
|
flavourSet.appendFlavour("text/x-moz-url");
|
||||||
flavourSet.appendFlavour("text/plain");
|
flavourSet.appendFlavour("text/plain");
|
||||||
flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
|
flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
|
||||||
|
|
|
@ -1912,10 +1912,13 @@
|
||||||
if (target.localName == "tab" &&
|
if (target.localName == "tab" &&
|
||||||
aEvent.originalTarget.localName != "toolbarbutton") {
|
aEvent.originalTarget.localName != "toolbarbutton") {
|
||||||
var dt = aEvent.dataTransfer;
|
var dt = aEvent.dataTransfer;
|
||||||
dt.mozSetDataAt("application/x-moz-tabbrowser-tab", target, 0);
|
dt.mozSetDataAt(TAB_DROP_TYPE, target, 0);
|
||||||
var uri = this.getBrowserForTab(aEvent.target).currentURI;
|
var uri = this.getBrowserForTab(aEvent.target).currentURI;
|
||||||
var spec = uri ? uri.spec : "about:blank";
|
var spec = uri ? uri.spec : "about:blank";
|
||||||
dt.mozSetDataAt("text/x-moz-url", spec + "\n" + aEvent.target.label, 0);
|
|
||||||
|
// We must not set text/x-moz-url data, otherwise trying to deatch
|
||||||
|
// the tab by dropping it on the desktop would result in an
|
||||||
|
// "internet shortcut"
|
||||||
dt.mozSetDataAt("text/plain", spec, 0);
|
dt.mozSetDataAt("text/plain", spec, 0);
|
||||||
|
|
||||||
var canvas = tabPreviews.capture(target, false);
|
var canvas = tabPreviews.capture(target, false);
|
||||||
|
@ -1947,8 +1950,8 @@
|
||||||
var types = dt.mozTypesAt(0);
|
var types = dt.mozTypesAt(0);
|
||||||
var sourceNode = null;
|
var sourceNode = null;
|
||||||
// tabs are always added as the first type
|
// tabs are always added as the first type
|
||||||
if (types[0] == "application/x-moz-tabbrowser-tab") {
|
if (types[0] == TAB_DROP_TYPE) {
|
||||||
var sourceNode = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
|
var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||||
if (sourceNode instanceof XULElement &&
|
if (sourceNode instanceof XULElement &&
|
||||||
sourceNode.localName == "tab" &&
|
sourceNode.localName == "tab" &&
|
||||||
(sourceNode.parentNode == this.mTabContainer ||
|
(sourceNode.parentNode == this.mTabContainer ||
|
||||||
|
@ -2086,7 +2089,7 @@
|
||||||
var dropEffect = dt.dropEffect;
|
var dropEffect = dt.dropEffect;
|
||||||
var draggedTab;
|
var draggedTab;
|
||||||
if (dropEffect != "link") { // copy or move
|
if (dropEffect != "link") { // copy or move
|
||||||
draggedTab = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
|
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||||
// not our drop then
|
// not our drop then
|
||||||
if (!draggedTab)
|
if (!draggedTab)
|
||||||
return;
|
return;
|
||||||
|
@ -2209,7 +2212,7 @@
|
||||||
// 2. Drop on some other tabbar
|
// 2. Drop on some other tabbar
|
||||||
// 3. Drop on text fields (even outside our window)
|
// 3. Drop on text fields (even outside our window)
|
||||||
if (dt.dropEffect == "none") {
|
if (dt.dropEffect == "none") {
|
||||||
var draggedTab = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
|
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||||
this.replaceTabWithWindow(draggedTab);
|
this.replaceTabWithWindow(draggedTab);
|
||||||
}
|
}
|
||||||
aEvent.stopPropagation();
|
aEvent.stopPropagation();
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
* for shared application glue for the Communicator suite of applications
|
* for shared application glue for the Communicator suite of applications
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
||||||
|
|
||||||
var gBidiUI = false;
|
var gBidiUI = false;
|
||||||
|
|
||||||
function getBrowserURL()
|
function getBrowserURL()
|
||||||
|
|
|
@ -1335,6 +1335,19 @@ var PlacesControllerDragHelper = {
|
||||||
|
|
||||||
var data = dt.mozGetDataAt(flavor, i);
|
var data = dt.mozGetDataAt(flavor, i);
|
||||||
|
|
||||||
|
// urls can be dropped on any insertionpoint
|
||||||
|
// XXXmano: // Remember: this method is called for each dragover event!
|
||||||
|
// Thus we shouldn't use unwrapNodes here at all if possible.
|
||||||
|
// I think it would be OK to accept bogus data here (e.g. text which was
|
||||||
|
// somehow wrapped as TAB_DROP_TYPE, this is not in our control, and
|
||||||
|
// will just case the actual drop to be a no-op), and only rule out valid
|
||||||
|
// expected cases, which are either unsupported flavors, or items which
|
||||||
|
// cannot be dropped in the current insertionpoint. The last case will
|
||||||
|
// likely force us to use unwrapNodes for the private data types of
|
||||||
|
// places.
|
||||||
|
if (flavor == TAB_DROP_TYPE)
|
||||||
|
continue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var dragged = PlacesUtils.unwrapNodes(data, flavor)[0];
|
var dragged = PlacesUtils.unwrapNodes(data, flavor)[0];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1363,6 +1376,7 @@ var PlacesControllerDragHelper = {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if a node can be moved.
|
* Determines if a node can be moved.
|
||||||
*
|
*
|
||||||
|
@ -1444,8 +1458,22 @@ var PlacesControllerDragHelper = {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var data = dt.mozGetDataAt(flavor, i);
|
var data = dt.mozGetDataAt(flavor, i);
|
||||||
// There's only ever one in the D&D case.
|
var unwrapped;
|
||||||
var unwrapped = PlacesUtils.unwrapNodes(data, flavor)[0];
|
if (flavor != TAB_DROP_TYPE) {
|
||||||
|
// There's only ever one in the D&D case.
|
||||||
|
unwrapped = PlacesUtils.unwrapNodes(data, flavor)[0];
|
||||||
|
}
|
||||||
|
else if (data instanceof XULElement && data.localName == "tab" &&
|
||||||
|
data.ownerDocument.defaultView instanceof ChromeWindow) {
|
||||||
|
var uri = data.linkedBrowser.currentURI;
|
||||||
|
var spec = uri ? uri.spec : "about:blank";
|
||||||
|
var title = data.label;
|
||||||
|
unwrapped = { uri: spec,
|
||||||
|
title: data.label,
|
||||||
|
type: PlacesUtils.TYPE_X_MOZ_URL};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw("bogus data was passed as a tab")
|
||||||
|
|
||||||
var index = insertionPoint.index;
|
var index = insertionPoint.index;
|
||||||
|
|
||||||
|
@ -1494,10 +1522,12 @@ var PlacesControllerDragHelper = {
|
||||||
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
|
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
|
||||||
PlacesUtils.TYPE_X_MOZ_PLACE],
|
PlacesUtils.TYPE_X_MOZ_PLACE],
|
||||||
|
|
||||||
|
// The order matters.
|
||||||
GENERIC_VIEW_DROP_TYPES: [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
|
GENERIC_VIEW_DROP_TYPES: [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
|
||||||
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
|
PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
|
||||||
PlacesUtils.TYPE_X_MOZ_PLACE,
|
PlacesUtils.TYPE_X_MOZ_PLACE,
|
||||||
PlacesUtils.TYPE_X_MOZ_URL,
|
PlacesUtils.TYPE_X_MOZ_URL,
|
||||||
|
TAB_DROP_TYPE,
|
||||||
PlacesUtils.TYPE_UNICODE],
|
PlacesUtils.TYPE_UNICODE],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -386,8 +386,9 @@ var PlacesUIUtils = {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (type == PlacesUtils.TYPE_X_MOZ_URL ||
|
if (type == PlacesUtils.TYPE_X_MOZ_URL ||
|
||||||
type == PlacesUtils.TYPE_UNICODE) {
|
type == PlacesUtils.TYPE_UNICODE ||
|
||||||
var title = (type == PlacesUtils.TYPE_X_MOZ_URL) ? data.title :
|
type == TAB_DROP_TYPE) {
|
||||||
|
var title = (type != PlacesUtils.TYPE_UNICODE) ? data.title :
|
||||||
data.uri;
|
data.uri;
|
||||||
return this.ptm.createItem(PlacesUtils._uri(data.uri),
|
return this.ptm.createItem(PlacesUtils._uri(data.uri),
|
||||||
container, index, title);
|
container, index, title);
|
||||||
|
|
|
@ -201,6 +201,10 @@ SessionStoreService.prototype = {
|
||||||
// observe prefs changes so we can modify stored data to match
|
// observe prefs changes so we can modify stored data to match
|
||||||
this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true);
|
this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true);
|
||||||
|
|
||||||
|
// this pref is only read at startup, so no need to observe it
|
||||||
|
this._sessionhistory_max_entries =
|
||||||
|
this._prefBranch.getIntPref("sessionhistory.max_entries");
|
||||||
|
|
||||||
// get file references
|
// get file references
|
||||||
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||||
getService(Ci.nsIProperties);
|
getService(Ci.nsIProperties);
|
||||||
|
@ -1007,8 +1011,11 @@ SessionStoreService.prototype = {
|
||||||
}
|
}
|
||||||
catch (ex) { } // this could happen if we catch a tab during (de)initialization
|
catch (ex) { } // this could happen if we catch a tab during (de)initialization
|
||||||
|
|
||||||
|
// XXXzeniko anchor navigation doesn't reset __SS_data, so we could reuse
|
||||||
|
// data even when we shouldn't (e.g. Back, different anchor)
|
||||||
if (history && browser.parentNode.__SS_data &&
|
if (history && browser.parentNode.__SS_data &&
|
||||||
browser.parentNode.__SS_data.entries[history.index] && !aFullData) {
|
browser.parentNode.__SS_data.entries[history.index] &&
|
||||||
|
history.index < this._sessionhistory_max_entries - 1 && !aFullData) {
|
||||||
tabData = browser.parentNode.__SS_data;
|
tabData = browser.parentNode.__SS_data;
|
||||||
tabData.index = history.index + 1;
|
tabData.index = history.index + 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_393716.js \
|
browser_393716.js \
|
||||||
browser_408470.js \
|
browser_408470.js \
|
||||||
browser_408470_sample.html \
|
browser_408470_sample.html \
|
||||||
|
browser_447951.js \
|
||||||
|
browser_447951_sample.html \
|
||||||
browser_448741.js \
|
browser_448741.js \
|
||||||
browser_454908.js \
|
browser_454908.js \
|
||||||
browser_454908_sample.html \
|
browser_454908_sample.html \
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is sessionstore test code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Simon Bünzli <zeniko@gmail.com>.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
/** Test for Bug 447951 **/
|
||||||
|
|
||||||
|
// test setup
|
||||||
|
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||||
|
waitForExplicitFinish();
|
||||||
|
const baseURL = "http://localhost:8888/browser/" +
|
||||||
|
"browser/components/sessionstore/test/browser/browser_447951_sample.html#";
|
||||||
|
|
||||||
|
let tab = gBrowser.addTab();
|
||||||
|
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||||
|
this.removeEventListener("load", arguments.callee, true);
|
||||||
|
|
||||||
|
let tabState = { entries: [] };
|
||||||
|
let max_entries = gPrefService.getIntPref("browser.sessionhistory.max_entries");
|
||||||
|
for (let i = 0; i < max_entries; i++)
|
||||||
|
tabState.entries.push({ url: baseURL + i });
|
||||||
|
|
||||||
|
ss.setTabState(tab, JSON.stringify(tabState));
|
||||||
|
tab.addEventListener("SSTabRestored", function(aEvent) {
|
||||||
|
this.removeEventListener("SSTabRestored", arguments.callee, false);
|
||||||
|
tabState = eval("(" + ss.getTabState(tab) + ")");
|
||||||
|
is(tabState.entries.length, max_entries, "session history filled to the limit");
|
||||||
|
is(tabState.entries[0].url, baseURL + 0, "... but not more");
|
||||||
|
|
||||||
|
// visit yet another anchor (appending it to session history)
|
||||||
|
let doc = tab.linkedBrowser.contentDocument;
|
||||||
|
let event = doc.createEvent("MouseEvents");
|
||||||
|
event.initMouseEvent("click", true, true, doc.defaultView, 1,
|
||||||
|
0, 0, 0, 0, false, false, false, false, 0, null);
|
||||||
|
doc.querySelector("a").dispatchEvent(event);
|
||||||
|
|
||||||
|
executeSoon(function() {
|
||||||
|
tabState = eval("(" + ss.getTabState(tab) + ")");
|
||||||
|
is(tab.linkedBrowser.currentURI.spec, baseURL + "end",
|
||||||
|
"the new anchor was loaded");
|
||||||
|
is(tabState.entries[tabState.entries.length - 1].url, baseURL + "end",
|
||||||
|
"... and ignored");
|
||||||
|
is(tabState.entries[0].url, baseURL + 1,
|
||||||
|
"... and the first item was removed");
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}, false);
|
||||||
|
}, true);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Testcase for bug 447951</title>
|
||||||
|
|
||||||
|
<a href="#end">click me</a>
|
|
@ -3819,18 +3819,20 @@ nsCanvasRenderingContext2D::PutImageData()
|
||||||
PRUint8 ir, ig, ib, ia;
|
PRUint8 ir, ig, ib, ia;
|
||||||
PRUint8 *ptr = imgPtr;
|
PRUint8 *ptr = imgPtr;
|
||||||
for (int32 i = 0; i < w*h; i++) {
|
for (int32 i = 0; i < w*h; i++) {
|
||||||
#ifdef IS_LITTLE_ENDIAN
|
|
||||||
ir = ptr[0];
|
ir = ptr[0];
|
||||||
ig = ptr[1];
|
ig = ptr[1];
|
||||||
ib = ptr[2];
|
ib = ptr[2];
|
||||||
ia = ptr[3];
|
ia = ptr[3];
|
||||||
|
|
||||||
|
#ifdef IS_LITTLE_ENDIAN
|
||||||
ptr[0] = (ib*ia + 254) / 255;
|
ptr[0] = (ib*ia + 254) / 255;
|
||||||
ptr[1] = (ig*ia + 254) / 255;
|
ptr[1] = (ig*ia + 254) / 255;
|
||||||
ptr[2] = (ir*ia + 254) / 255;
|
ptr[2] = (ir*ia + 254) / 255;
|
||||||
#else
|
#else
|
||||||
ptr[0] = (ptr[0]*ptr[3] + 254) / 255;
|
ptr[0] = ia;
|
||||||
ptr[1] = (ptr[1]*ptr[3] + 254) / 255;
|
ptr[1] = (ir*ia + 254) / 255;
|
||||||
ptr[2] = (ptr[2]*ptr[3] + 254) / 255;
|
ptr[2] = (ig*ia + 254) / 255;
|
||||||
|
ptr[3] = (ib*ia + 254) / 255;
|
||||||
#endif
|
#endif
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,9 +137,8 @@ nsDOMUIEvent::GetScreenPoint()
|
||||||
return mEvent->refPoint;
|
return mEvent->refPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIntRect bounds(mEvent->refPoint, nsIntSize(1, 1));
|
nsIntPoint offset = mEvent->refPoint +
|
||||||
nsIntRect offset;
|
((nsGUIEvent*)mEvent)->widget->WidgetToScreenOffset();
|
||||||
((nsGUIEvent*)mEvent)->widget->WidgetToScreen ( bounds, offset );
|
|
||||||
nscoord factor = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
|
nscoord factor = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
|
||||||
return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
|
return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
|
||||||
nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
|
nsPresContext::AppUnitsToIntCSSPixels(offset.y * factor));
|
||||||
|
|
|
@ -593,10 +593,7 @@ nsMouseWheelTransaction::GetScreenPoint(nsGUIEvent* aEvent)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aEvent, "aEvent is null");
|
NS_ASSERTION(aEvent, "aEvent is null");
|
||||||
NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
|
NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
|
||||||
nsIntRect tmpRect;
|
return aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||||
aEvent->widget->WidgetToScreen(nsIntRect(aEvent->refPoint, nsIntSize(1, 1)),
|
|
||||||
tmpRect);
|
|
||||||
return tmpRect.TopLeft();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32
|
PRUint32
|
||||||
|
@ -2087,10 +2084,8 @@ nsEventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext,
|
||||||
{
|
{
|
||||||
// Note that |inDownEvent| could be either a mouse down event or a
|
// Note that |inDownEvent| could be either a mouse down event or a
|
||||||
// synthesized mouse move event.
|
// synthesized mouse move event.
|
||||||
nsIntRect screenPt;
|
mGestureDownPoint = inDownEvent->refPoint +
|
||||||
inDownEvent->widget->WidgetToScreen(nsIntRect(inDownEvent->refPoint, nsIntSize(1, 1)),
|
inDownEvent->widget->WidgetToScreenOffset();
|
||||||
screenPt);
|
|
||||||
mGestureDownPoint = screenPt.TopLeft();
|
|
||||||
|
|
||||||
inDownFrame->GetContentForEvent(aPresContext, inDownEvent,
|
inDownFrame->GetContentForEvent(aPresContext, inDownEvent,
|
||||||
getter_AddRefs(mGestureDownContent));
|
getter_AddRefs(mGestureDownContent));
|
||||||
|
@ -2131,9 +2126,8 @@ nsEventStateManager::FillInEventFromGestureDown(nsMouseEvent* aEvent)
|
||||||
// Set the coordinates in the new event to the coordinates of
|
// Set the coordinates in the new event to the coordinates of
|
||||||
// the old event, adjusted for the fact that the widget might be
|
// the old event, adjusted for the fact that the widget might be
|
||||||
// different
|
// different
|
||||||
nsIntRect tmpRect(0, 0, 1, 1);
|
nsIntPoint tmpPoint = aEvent->widget->WidgetToScreenOffset();
|
||||||
aEvent->widget->WidgetToScreen(tmpRect, tmpRect);
|
aEvent->refPoint = mGestureDownPoint - tmpPoint;
|
||||||
aEvent->refPoint = mGestureDownPoint - tmpRect.TopLeft();
|
|
||||||
aEvent->isShift = mGestureDownShift;
|
aEvent->isShift = mGestureDownShift;
|
||||||
aEvent->isControl = mGestureDownControl;
|
aEvent->isControl = mGestureDownControl;
|
||||||
aEvent->isAlt = mGestureDownAlt;
|
aEvent->isAlt = mGestureDownAlt;
|
||||||
|
@ -2192,10 +2186,7 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
// fire drag gesture if mouse has moved enough
|
// fire drag gesture if mouse has moved enough
|
||||||
nsIntRect tmpRect;
|
nsIntPoint pt = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||||
aEvent->widget->WidgetToScreen(nsIntRect(aEvent->refPoint, nsIntSize(1, 1)),
|
|
||||||
tmpRect);
|
|
||||||
nsIntPoint pt = tmpRect.TopLeft();
|
|
||||||
if (PR_ABS(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
|
if (PR_ABS(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
|
||||||
PR_ABS(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
|
PR_ABS(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
|
||||||
#ifdef CLICK_HOLD_CONTEXT_MENUS
|
#ifdef CLICK_HOLD_CONTEXT_MENUS
|
||||||
|
|
|
@ -92,30 +92,12 @@ class nsAudioStream
|
||||||
// Block until buffered audio data has been consumed.
|
// Block until buffered audio data has been consumed.
|
||||||
void Drain();
|
void Drain();
|
||||||
|
|
||||||
// Pause sound playback.
|
|
||||||
void Pause();
|
|
||||||
|
|
||||||
// Resume sound playback.
|
|
||||||
void Resume();
|
|
||||||
|
|
||||||
// Return the position (in seconds) of the audio sample currently being
|
|
||||||
// played by the audio hardware.
|
|
||||||
double GetTime();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double mVolume;
|
double mVolume;
|
||||||
void* mAudioHandle;
|
void* mAudioHandle;
|
||||||
int mRate;
|
int mRate;
|
||||||
int mChannels;
|
int mChannels;
|
||||||
|
|
||||||
// The byte position in the audio buffer where playback was last paused.
|
|
||||||
PRInt64 mSavedPauseBytes;
|
|
||||||
PRInt64 mPauseBytes;
|
|
||||||
|
|
||||||
float mStartTime;
|
|
||||||
float mPauseTime;
|
|
||||||
PRInt64 mSamplesBuffered;
|
|
||||||
|
|
||||||
SampleFormat mFormat;
|
SampleFormat mFormat;
|
||||||
|
|
||||||
// When a Write() request is made, and the number of samples
|
// When a Write() request is made, and the number of samples
|
||||||
|
@ -123,7 +105,5 @@ class nsAudioStream
|
||||||
// backend, the remaining samples are stored in this variable. They
|
// backend, the remaining samples are stored in this variable. They
|
||||||
// will be written on the next Write() request.
|
// will be written on the next Write() request.
|
||||||
nsTArray<short> mBufferOverflow;
|
nsTArray<short> mBufferOverflow;
|
||||||
|
|
||||||
PRPackedBool mPaused;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -67,10 +67,6 @@ public:
|
||||||
// request to return an error. Call on main thread only.
|
// request to return an error. Call on main thread only.
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
||||||
// Return the number of bytes buffered from the file. This can safely
|
|
||||||
// be read without blocking.
|
|
||||||
PRUint32 Available();
|
|
||||||
|
|
||||||
// Suspend any downloads that are in progress.
|
// Suspend any downloads that are in progress.
|
||||||
void Suspend();
|
void Suspend();
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,6 @@ public:
|
||||||
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes) = 0;
|
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes) = 0;
|
||||||
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0;
|
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0;
|
||||||
virtual PRInt64 Tell() = 0;
|
virtual PRInt64 Tell() = 0;
|
||||||
virtual PRUint32 Available() = 0;
|
|
||||||
virtual void Cancel() { }
|
virtual void Cancel() { }
|
||||||
virtual nsIPrincipal* GetCurrentPrincipal() = 0;
|
virtual nsIPrincipal* GetCurrentPrincipal() = 0;
|
||||||
virtual void Suspend() = 0;
|
virtual void Suspend() = 0;
|
||||||
|
@ -172,10 +171,6 @@ class nsMediaStream
|
||||||
// Can be called from any thread.
|
// Can be called from any thread.
|
||||||
PRInt64 Tell();
|
PRInt64 Tell();
|
||||||
|
|
||||||
// Return the number of bytes available in the stream that can be
|
|
||||||
// read without blocking. Can be called from any thread.
|
|
||||||
PRUint32 Available();
|
|
||||||
|
|
||||||
// Cancels any currently blocking request and forces that request to
|
// Cancels any currently blocking request and forces that request to
|
||||||
// return an error. Call on main thread only.
|
// return an error. Call on main thread only.
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
|
@ -200,6 +200,8 @@ class nsWaveDecoder : public nsMediaDecoder
|
||||||
|
|
||||||
virtual void SetTotalBytes(PRInt64 aBytes);
|
virtual void SetTotalBytes(PRInt64 aBytes);
|
||||||
|
|
||||||
|
void PlaybackPositionChanged();
|
||||||
|
|
||||||
// Setter for the duration. This is ignored by the wave decoder since it can
|
// Setter for the duration. This is ignored by the wave decoder since it can
|
||||||
// compute the duration directly from the wave data.
|
// compute the duration directly from the wave data.
|
||||||
virtual void SetDuration(PRInt64 aDuration);
|
virtual void SetDuration(PRInt64 aDuration);
|
||||||
|
@ -268,6 +270,12 @@ private:
|
||||||
// state machine will validate the offset against the current media.
|
// state machine will validate the offset against the current media.
|
||||||
float mTimeOffset;
|
float mTimeOffset;
|
||||||
|
|
||||||
|
// The current playback position of the media resource in units of
|
||||||
|
// seconds. This is updated every time a block of audio is passed to the
|
||||||
|
// backend (unless an prior update is still pending). It is read and
|
||||||
|
// written from the main thread only.
|
||||||
|
float mCurrentTime;
|
||||||
|
|
||||||
// Copy of the current time, duration, and ended state when the state
|
// Copy of the current time, duration, and ended state when the state
|
||||||
// machine was disposed. Used to respond to time and duration queries
|
// machine was disposed. Used to respond to time and duration queries
|
||||||
// with sensible values after the state machine is destroyed.
|
// with sensible values after the state machine is destroyed.
|
||||||
|
|
|
@ -52,11 +52,6 @@ PRLogModuleInfo* gAudioStreamLog = nsnull;
|
||||||
|
|
||||||
#define FAKE_BUFFER_SIZE 176400
|
#define FAKE_BUFFER_SIZE 176400
|
||||||
|
|
||||||
static float CurrentTimeInSeconds()
|
|
||||||
{
|
|
||||||
return PR_IntervalToMilliseconds(PR_IntervalNow()) / 1000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsAudioStream::InitLibrary()
|
void nsAudioStream::InitLibrary()
|
||||||
{
|
{
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
|
@ -73,12 +68,7 @@ nsAudioStream::nsAudioStream() :
|
||||||
mAudioHandle(0),
|
mAudioHandle(0),
|
||||||
mRate(0),
|
mRate(0),
|
||||||
mChannels(0),
|
mChannels(0),
|
||||||
mSavedPauseBytes(0),
|
mFormat(FORMAT_S16_LE)
|
||||||
mPauseBytes(0),
|
|
||||||
mPauseTime(0.0),
|
|
||||||
mSamplesBuffered(0),
|
|
||||||
mFormat(FORMAT_S16_LE),
|
|
||||||
mPaused(PR_FALSE)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +77,6 @@ void nsAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aForm
|
||||||
mRate = aRate;
|
mRate = aRate;
|
||||||
mChannels = aNumChannels;
|
mChannels = aNumChannels;
|
||||||
mFormat = aFormat;
|
mFormat = aFormat;
|
||||||
mStartTime = CurrentTimeInSeconds();
|
|
||||||
if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
|
if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
|
||||||
NULL,
|
NULL,
|
||||||
SA_MODE_WRONLY,
|
SA_MODE_WRONLY,
|
||||||
|
@ -121,7 +110,6 @@ void nsAudioStream::Write(const void* aBuf, PRUint32 aCount)
|
||||||
NS_ABORT_IF_FALSE(aCount % mChannels == 0,
|
NS_ABORT_IF_FALSE(aCount % mChannels == 0,
|
||||||
"Buffer size must be divisible by channel count");
|
"Buffer size must be divisible by channel count");
|
||||||
|
|
||||||
mSamplesBuffered += aCount;
|
|
||||||
PRUint32 offset = mBufferOverflow.Length();
|
PRUint32 offset = mBufferOverflow.Length();
|
||||||
PRInt32 count = aCount + offset;
|
PRInt32 count = aCount + offset;
|
||||||
|
|
||||||
|
@ -214,13 +202,8 @@ void nsAudioStream::SetVolume(float aVolume)
|
||||||
|
|
||||||
void nsAudioStream::Drain()
|
void nsAudioStream::Drain()
|
||||||
{
|
{
|
||||||
if (!mAudioHandle) {
|
if (!mAudioHandle)
|
||||||
// mSamplesBuffered already accounts for the data in the
|
|
||||||
// mBufferOverflow array.
|
|
||||||
PRUint32 drainTime = (float(mSamplesBuffered) / mRate / mChannels - GetTime()) * 1000.0;
|
|
||||||
PR_Sleep(PR_MillisecondsToInterval(drainTime));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Write any remaining unwritten sound data in the overflow buffer
|
// Write any remaining unwritten sound data in the overflow buffer
|
||||||
if (!mBufferOverflow.IsEmpty()) {
|
if (!mBufferOverflow.IsEmpty()) {
|
||||||
|
@ -235,69 +218,3 @@ void nsAudioStream::Drain()
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsAudioStream::Pause()
|
|
||||||
{
|
|
||||||
if (mPaused)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Save the elapsed playback time. Used to offset the wall-clock time
|
|
||||||
// when resuming.
|
|
||||||
mPauseTime = CurrentTimeInSeconds() - mStartTime;
|
|
||||||
|
|
||||||
mPaused = PR_TRUE;
|
|
||||||
|
|
||||||
if (!mAudioHandle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int64_t bytes = 0;
|
|
||||||
#if !defined(WIN32)
|
|
||||||
sa_stream_get_position(static_cast<sa_stream_t*>(mAudioHandle), SA_POSITION_WRITE_SOFTWARE, &bytes);
|
|
||||||
#endif
|
|
||||||
mSavedPauseBytes = bytes;
|
|
||||||
|
|
||||||
sa_stream_pause(static_cast<sa_stream_t*>(mAudioHandle));
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsAudioStream::Resume()
|
|
||||||
{
|
|
||||||
if (!mPaused)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Reset the start time to the current time offset backwards by the
|
|
||||||
// elapsed time saved when the stream paused.
|
|
||||||
mStartTime = CurrentTimeInSeconds() - mPauseTime;
|
|
||||||
|
|
||||||
mPaused = PR_FALSE;
|
|
||||||
|
|
||||||
if (!mAudioHandle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sa_stream_resume(static_cast<sa_stream_t*>(mAudioHandle));
|
|
||||||
|
|
||||||
#if !defined(WIN32)
|
|
||||||
mPauseBytes += mSavedPauseBytes;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
double nsAudioStream::GetTime()
|
|
||||||
{
|
|
||||||
// If the audio backend failed to open, emulate the current playback
|
|
||||||
// position using the system clock.
|
|
||||||
if (!mAudioHandle) {
|
|
||||||
if (mPaused) {
|
|
||||||
return mPauseTime;
|
|
||||||
}
|
|
||||||
float curTime = CurrentTimeInSeconds() - mStartTime;
|
|
||||||
float maxTime = float(mSamplesBuffered) / mRate / mChannels;
|
|
||||||
return NS_MIN(curTime, maxTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t bytes = 0;
|
|
||||||
#if defined(WIN32)
|
|
||||||
sa_stream_get_position(static_cast<sa_stream_t*>(mAudioHandle), SA_POSITION_WRITE_HARDWARE, &bytes);
|
|
||||||
#else
|
|
||||||
sa_stream_get_position(static_cast<sa_stream_t*>(mAudioHandle), SA_POSITION_WRITE_SOFTWARE, &bytes);
|
|
||||||
#endif
|
|
||||||
return double(bytes + mPauseBytes) / (sizeof(short) * mChannels * mRate);
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,11 +48,6 @@ void nsChannelReader::Cancel()
|
||||||
mStream.Cancel();
|
mStream.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 nsChannelReader::Available()
|
|
||||||
{
|
|
||||||
return mStream.Available();
|
|
||||||
}
|
|
||||||
|
|
||||||
OggPlayErrorCode nsChannelReader::initialise(int aBlock)
|
OggPlayErrorCode nsChannelReader::initialise(int aBlock)
|
||||||
{
|
{
|
||||||
return E_OGGPLAY_OK;
|
return E_OGGPLAY_OK;
|
||||||
|
|
|
@ -71,7 +71,6 @@ public:
|
||||||
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
|
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
|
||||||
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
|
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
|
||||||
virtual PRInt64 Tell();
|
virtual PRInt64 Tell();
|
||||||
virtual PRUint32 Available();
|
|
||||||
virtual void Cancel();
|
virtual void Cancel();
|
||||||
virtual nsIPrincipal* GetCurrentPrincipal();
|
virtual nsIPrincipal* GetCurrentPrincipal();
|
||||||
virtual void Suspend();
|
virtual void Suspend();
|
||||||
|
@ -186,20 +185,6 @@ PRInt64 nsDefaultStreamStrategy::Tell()
|
||||||
return mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 nsDefaultStreamStrategy::Available()
|
|
||||||
{
|
|
||||||
// The request pulls from the pipe, not the channels input
|
|
||||||
// stream. This allows calling from any thread as the pipe is
|
|
||||||
// threadsafe.
|
|
||||||
nsAutoLock lock(mLock);
|
|
||||||
if (!mPipeInput)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
PRUint32 count = 0;
|
|
||||||
mPipeInput->Available(&count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsDefaultStreamStrategy::Cancel()
|
void nsDefaultStreamStrategy::Cancel()
|
||||||
{
|
{
|
||||||
if (mListener)
|
if (mListener)
|
||||||
|
@ -239,7 +224,6 @@ public:
|
||||||
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
|
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
|
||||||
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
|
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
|
||||||
virtual PRInt64 Tell();
|
virtual PRInt64 Tell();
|
||||||
virtual PRUint32 Available();
|
|
||||||
virtual nsIPrincipal* GetCurrentPrincipal();
|
virtual nsIPrincipal* GetCurrentPrincipal();
|
||||||
virtual void Suspend();
|
virtual void Suspend();
|
||||||
virtual void Resume();
|
virtual void Resume();
|
||||||
|
@ -419,17 +403,6 @@ PRInt64 nsFileStreamStrategy::Tell()
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 nsFileStreamStrategy::Available()
|
|
||||||
{
|
|
||||||
nsAutoLock lock(mLock);
|
|
||||||
if (!mInput)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
PRUint32 count = 0;
|
|
||||||
mInput->Available(&count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIPrincipal* nsFileStreamStrategy::GetCurrentPrincipal()
|
nsIPrincipal* nsFileStreamStrategy::GetCurrentPrincipal()
|
||||||
{
|
{
|
||||||
return mPrincipal;
|
return mPrincipal;
|
||||||
|
@ -463,7 +436,6 @@ public:
|
||||||
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
|
virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
|
||||||
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
|
virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
|
||||||
virtual PRInt64 Tell();
|
virtual PRInt64 Tell();
|
||||||
virtual PRUint32 Available();
|
|
||||||
virtual void Cancel();
|
virtual void Cancel();
|
||||||
virtual nsIPrincipal* GetCurrentPrincipal();
|
virtual nsIPrincipal* GetCurrentPrincipal();
|
||||||
virtual void Suspend();
|
virtual void Suspend();
|
||||||
|
@ -763,12 +735,13 @@ nsresult nsHttpStreamStrategy::Seek(PRInt32 aWhence, PRInt64 aOffset)
|
||||||
bytesRead += bytes;
|
bytesRead += bytes;
|
||||||
} while (bytesRead != bytesAhead);
|
} while (bytesRead != bytesAhead);
|
||||||
|
|
||||||
// We don't need to notify the decoder here that we seeked. It will
|
// We don't need to notify the decoder here that we seeked, just that
|
||||||
// look like we just read ahead a bit. In fact, we mustn't tell
|
// we read ahead. In fact, we mustn't tell the decoder that we seeked,
|
||||||
// the decoder that we seeked, since the seek notification might
|
// since the seek notification might race with the "data downloaded"
|
||||||
// race with the "data downloaded" notification after the data was
|
// notification after the data was written into the pipe, so that the
|
||||||
// written into the pipe, so that the seek notification
|
// seek notification happens *first*, hopelessly confusing the
|
||||||
// happens *first*, hopelessly confusing the decoder.
|
// decoder.
|
||||||
|
mDecoder->NotifyBytesConsumed(bytesRead);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -795,20 +768,6 @@ PRInt64 nsHttpStreamStrategy::Tell()
|
||||||
return mAtEOF ? mDecoder->GetStatistics().mTotalBytes : mPosition;
|
return mAtEOF ? mDecoder->GetStatistics().mTotalBytes : mPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 nsHttpStreamStrategy::Available()
|
|
||||||
{
|
|
||||||
// The request pulls from the pipe, not the channels input
|
|
||||||
// stream. This allows calling from any thread as the pipe is
|
|
||||||
// threadsafe.
|
|
||||||
nsAutoLock lock(mLock);
|
|
||||||
if (!mPipeInput)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
PRUint32 count = 0;
|
|
||||||
mPipeInput->Available(&count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsHttpStreamStrategy::Cancel()
|
void nsHttpStreamStrategy::Cancel()
|
||||||
{
|
{
|
||||||
mCancelled = PR_TRUE;
|
mCancelled = PR_TRUE;
|
||||||
|
@ -909,11 +868,6 @@ PRInt64 nsMediaStream::Tell()
|
||||||
return mStreamStrategy->Tell();
|
return mStreamStrategy->Tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 nsMediaStream::Available()
|
|
||||||
{
|
|
||||||
return mStreamStrategy->Available();
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsMediaStream::Cancel()
|
void nsMediaStream::Cancel()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(),
|
NS_ASSERTION(NS_IsMainThread(),
|
||||||
|
|
|
@ -54,9 +54,13 @@
|
||||||
// Maximum number of seconds to wait when buffering.
|
// Maximum number of seconds to wait when buffering.
|
||||||
#define BUFFERING_TIMEOUT 3
|
#define BUFFERING_TIMEOUT 3
|
||||||
|
|
||||||
// The number of seconds of buffer data before buffering happens
|
// Duration the playback loop will sleep after refilling the backend's audio
|
||||||
// based on current playback rate.
|
// buffers. The loop's goal is to keep AUDIO_BUFFER_LENGTH milliseconds of
|
||||||
#define BUFFERING_SECONDS_LOW_WATER_MARK 1
|
// audio buffered to allow time to refill before the backend underruns.
|
||||||
|
// Should be a multiple of 10 to deal with poor timer granularity on some
|
||||||
|
// platforms.
|
||||||
|
#define AUDIO_BUFFER_WAKEUP 100
|
||||||
|
#define AUDIO_BUFFER_LENGTH (2 * AUDIO_BUFFER_WAKEUP)
|
||||||
|
|
||||||
// Magic values that identify RIFF chunks we're interested in.
|
// Magic values that identify RIFF chunks we're interested in.
|
||||||
#define RIFF_CHUNK_MAGIC 0x52494646
|
#define RIFF_CHUNK_MAGIC 0x52494646
|
||||||
|
@ -74,13 +78,21 @@
|
||||||
// extended (for non-PCM encodings), but we skip any extended data.
|
// extended (for non-PCM encodings), but we skip any extended data.
|
||||||
#define WAVE_FORMAT_CHUNK_SIZE 16
|
#define WAVE_FORMAT_CHUNK_SIZE 16
|
||||||
|
|
||||||
// Size of format chunk including RIFF chunk header.
|
|
||||||
#define WAVE_FORMAT_SIZE (RIFF_CHUNK_HEADER_SIZE + WAVE_FORMAT_CHUNK_SIZE)
|
|
||||||
|
|
||||||
// PCM encoding type from format chunk. Linear PCM is the only encoding
|
// PCM encoding type from format chunk. Linear PCM is the only encoding
|
||||||
// supported by nsAudioStream.
|
// supported by nsAudioStream.
|
||||||
#define WAVE_FORMAT_ENCODING_PCM 1
|
#define WAVE_FORMAT_ENCODING_PCM 1
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
STATE_LOADING_METADATA,
|
||||||
|
STATE_BUFFERING,
|
||||||
|
STATE_PLAYING,
|
||||||
|
STATE_SEEKING,
|
||||||
|
STATE_PAUSED,
|
||||||
|
STATE_ENDED,
|
||||||
|
STATE_ERROR,
|
||||||
|
STATE_SHUTDOWN
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A single nsWaveStateMachine instance is owned by the decoder, created
|
A single nsWaveStateMachine instance is owned by the decoder, created
|
||||||
on-demand at load time. Upon creation, the decoder immediately
|
on-demand at load time. Upon creation, the decoder immediately
|
||||||
|
@ -101,17 +113,6 @@
|
||||||
class nsWaveStateMachine : public nsRunnable
|
class nsWaveStateMachine : public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum State {
|
|
||||||
STATE_LOADING_METADATA,
|
|
||||||
STATE_BUFFERING,
|
|
||||||
STATE_PLAYING,
|
|
||||||
STATE_SEEKING,
|
|
||||||
STATE_PAUSED,
|
|
||||||
STATE_ENDED,
|
|
||||||
STATE_ERROR,
|
|
||||||
STATE_SHUTDOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
|
nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
|
||||||
PRUint32 aBufferWaitTime, float aInitialVolume);
|
PRUint32 aBufferWaitTime, float aInitialVolume);
|
||||||
~nsWaveStateMachine();
|
~nsWaveStateMachine();
|
||||||
|
@ -148,18 +149,9 @@ public:
|
||||||
// Returns true if the state machine has reached the end of playback. Threadsafe.
|
// Returns true if the state machine has reached the end of playback. Threadsafe.
|
||||||
PRBool IsEnded();
|
PRBool IsEnded();
|
||||||
|
|
||||||
// Called by the decoder to indicate that the media stream has closed.
|
|
||||||
// aAtEnd is true if we read to the end of the file.
|
|
||||||
void StreamEnded(PRBool aAtEnd);
|
|
||||||
|
|
||||||
// Main state machine loop. Runs forever, until shutdown state is reached.
|
// Main state machine loop. Runs forever, until shutdown state is reached.
|
||||||
NS_IMETHOD Run();
|
NS_IMETHOD Run();
|
||||||
|
|
||||||
// Called by the decoder when the SeekStarted event runs. This ensures
|
|
||||||
// the current time offset of the state machine is updated to the new seek
|
|
||||||
// position at the appropriate time.
|
|
||||||
void UpdateTimeOffset(float aTime);
|
|
||||||
|
|
||||||
// Called by the decoder, on the main thread.
|
// Called by the decoder, on the main thread.
|
||||||
nsMediaDecoder::Statistics GetStatistics();
|
nsMediaDecoder::Statistics GetStatistics();
|
||||||
|
|
||||||
|
@ -177,13 +169,19 @@ public:
|
||||||
// Called by the main thread only
|
// Called by the main thread only
|
||||||
nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus();
|
nsHTMLMediaElement::NextFrameStatus GetNextFrameStatus();
|
||||||
|
|
||||||
private:
|
// Clear the flag indicating that a playback position change event is
|
||||||
|
// currently queued and return the current time. This is called from the
|
||||||
|
// main thread.
|
||||||
|
float GetTimeForPositionChange();
|
||||||
|
|
||||||
|
private:
|
||||||
// Returns PR_TRUE if we're in shutdown state. Threadsafe.
|
// Returns PR_TRUE if we're in shutdown state. Threadsafe.
|
||||||
PRBool IsShutdown();
|
PRBool IsShutdown();
|
||||||
|
|
||||||
// Reads from the media stream. Returns PR_FALSE on failure or EOF.
|
// Reads from the media stream. Returns PR_FALSE on failure or EOF. If
|
||||||
PRBool ReadAll(char* aBuf, PRUint32 aSize);
|
// aBytesRead is non-null, the number of bytes read will be returned via
|
||||||
|
// this.
|
||||||
|
PRBool ReadAll(char* aBuf, PRInt64 aSize, PRInt64* aBytesRead);
|
||||||
|
|
||||||
// Change the current state and wake the playback thread if it is waiting
|
// Change the current state and wake the playback thread if it is waiting
|
||||||
// on mMonitor. Used by public member functions called from both threads,
|
// on mMonitor. Used by public member functions called from both threads,
|
||||||
|
@ -200,6 +198,11 @@ private:
|
||||||
// the stream data is a RIFF bitstream containing WAVE data.
|
// the stream data is a RIFF bitstream containing WAVE data.
|
||||||
PRBool LoadRIFFChunk();
|
PRBool LoadRIFFChunk();
|
||||||
|
|
||||||
|
// Read forward in the stream until aWantedChunk is found. Return chunk
|
||||||
|
// size in aChunkSize. aChunkSize will not be rounded up if the chunk
|
||||||
|
// size is odd.
|
||||||
|
PRBool ScanForwardUntil(PRUint32 aWantedChunk, PRUint32* aChunkSize);
|
||||||
|
|
||||||
// Scan forward in the stream looking for the WAVE format chunk. If
|
// Scan forward in the stream looking for the WAVE format chunk. If
|
||||||
// found, parse and validate required metadata, then use it to set
|
// found, parse and validate required metadata, then use it to set
|
||||||
// mSampleRate, mChannels, mSampleSize, and mSampleFormat.
|
// mSampleRate, mChannels, mSampleSize, and mSampleFormat.
|
||||||
|
@ -210,29 +213,40 @@ private:
|
||||||
// mWavePCMOffset.
|
// mWavePCMOffset.
|
||||||
PRBool FindDataOffset();
|
PRBool FindDataOffset();
|
||||||
|
|
||||||
|
// Return the length of the PCM data.
|
||||||
|
PRInt64 GetDataLength();
|
||||||
|
|
||||||
|
// Fire a PlaybackPositionChanged event. If aCoalesce is true and a
|
||||||
|
// PlaybackPositionChanged event is already pending, an event is not
|
||||||
|
// fired.
|
||||||
|
void FirePositionChanged(PRBool aCoalesce);
|
||||||
|
|
||||||
// Returns the number of seconds that aBytes represents based on the
|
// Returns the number of seconds that aBytes represents based on the
|
||||||
// current audio parameters. e.g. 176400 bytes is 1 second at 16-bit
|
// current audio parameters. e.g. 176400 bytes is 1 second at 16-bit
|
||||||
// stereo 44.1kHz.
|
// stereo 44.1kHz.
|
||||||
float BytesToTime(PRUint32 aBytes) const
|
float BytesToTime(PRInt64 aBytes) const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mMetadataValid, "Requires valid metadata");
|
NS_ABORT_IF_FALSE(mMetadataValid, "Requires valid metadata");
|
||||||
|
NS_ABORT_IF_FALSE(aBytes >= 0, "Must be >= 0");
|
||||||
return float(aBytes) / mSampleRate / mSampleSize;
|
return float(aBytes) / mSampleRate / mSampleSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes that aTime represents based on the current
|
// Returns the number of bytes that aTime represents based on the current
|
||||||
// audio parameters. e.g. 1 second is 176400 bytes at 16-bit stereo
|
// audio parameters. e.g. 1 second is 176400 bytes at 16-bit stereo
|
||||||
// 44.1kHz.
|
// 44.1kHz.
|
||||||
PRUint32 TimeToBytes(float aTime) const
|
PRInt64 TimeToBytes(float aTime) const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mMetadataValid, "Requires valid metadata");
|
NS_ABORT_IF_FALSE(mMetadataValid, "Requires valid metadata");
|
||||||
return PRUint32(aTime * mSampleRate * mSampleSize);
|
NS_ABORT_IF_FALSE(aTime >= 0.0, "Must be >= 0");
|
||||||
|
return RoundDownToSample(PRInt64(aTime * mSampleRate * mSampleSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rounds aBytes down to the nearest complete sample. Assumes beginning
|
// Rounds aBytes down to the nearest complete sample. Assumes beginning
|
||||||
// of byte range is already sample aligned by caller.
|
// of byte range is already sample aligned by caller.
|
||||||
PRUint32 RoundDownToSample(PRUint32 aBytes) const
|
PRInt64 RoundDownToSample(PRInt64 aBytes) const
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mMetadataValid, "Requires valid metadata");
|
NS_ABORT_IF_FALSE(mMetadataValid, "Requires valid metadata");
|
||||||
|
NS_ABORT_IF_FALSE(aBytes >= 0, "Must be >= 0");
|
||||||
return aBytes - (aBytes % mSampleSize);
|
return aBytes - (aBytes % mSampleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,16 +272,13 @@ private:
|
||||||
// Maximum time in milliseconds to spend waiting for data during buffering.
|
// Maximum time in milliseconds to spend waiting for data during buffering.
|
||||||
PRUint32 mBufferingWait;
|
PRUint32 mBufferingWait;
|
||||||
|
|
||||||
// Maximum number of bytes to wait for during buffering.
|
|
||||||
PRUint32 mBufferingBytes;
|
|
||||||
|
|
||||||
// Machine time that buffering began, used with mBufferingWait to time out
|
// Machine time that buffering began, used with mBufferingWait to time out
|
||||||
// buffering.
|
// buffering.
|
||||||
PRIntervalTime mBufferingStart;
|
PRIntervalTime mBufferingStart;
|
||||||
|
|
||||||
// Maximum number of bytes mAudioStream buffers internally. Used to
|
// Download position where we should stop buffering. Only accessed
|
||||||
// calculate next wakeup time after refilling audio buffers.
|
// in the decoder thread.
|
||||||
PRUint32 mAudioBufferSize;
|
PRInt64 mBufferingEndOffset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Metadata extracted from the WAVE header. Used to initialize the audio
|
Metadata extracted from the WAVE header. Used to initialize the audio
|
||||||
|
@ -289,11 +300,11 @@ private:
|
||||||
|
|
||||||
// Size of PCM data stored in the WAVE as reported by the data chunk in
|
// Size of PCM data stored in the WAVE as reported by the data chunk in
|
||||||
// the media.
|
// the media.
|
||||||
PRUint32 mWaveLength;
|
PRInt64 mWaveLength;
|
||||||
|
|
||||||
// Start offset of the PCM data in the media stream. Extends mWaveLength
|
// Start offset of the PCM data in the media stream. Extends mWaveLength
|
||||||
// bytes.
|
// bytes.
|
||||||
PRUint32 mWavePCMOffset;
|
PRInt64 mWavePCMOffset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
All member variables following this comment are accessed by both
|
All member variables following this comment are accessed by both
|
||||||
|
@ -326,15 +337,9 @@ private:
|
||||||
// Volume that the audio backend will be initialized with.
|
// Volume that the audio backend will be initialized with.
|
||||||
float mInitialVolume;
|
float mInitialVolume;
|
||||||
|
|
||||||
// Time position (in seconds) to offset current time from audio stream.
|
// Playback position (in bytes), updated as the playback loop runs and
|
||||||
// Set when the seek started event runs and when the stream is closed
|
// upon seeking.
|
||||||
// during shutdown.
|
PRInt64 mTimeOffset;
|
||||||
float mTimeOffset;
|
|
||||||
|
|
||||||
// Set when StreamEnded has fired to indicate that we should not expect
|
|
||||||
// any more data from mStream than what is already buffered (i.e. what
|
|
||||||
// Available() reports).
|
|
||||||
PRPackedBool mExpectMoreData;
|
|
||||||
|
|
||||||
// Time position (in seconds) to seek to. Set by Seek(float).
|
// Time position (in seconds) to seek to. Set by Seek(float).
|
||||||
float mSeekTime;
|
float mSeekTime;
|
||||||
|
@ -343,6 +348,12 @@ private:
|
||||||
// mChannels, mSampleSize, mSampleFormat, mWaveLength, mWavePCMOffset must
|
// mChannels, mSampleSize, mSampleFormat, mWaveLength, mWavePCMOffset must
|
||||||
// check this flag before assuming the values are valid.
|
// check this flag before assuming the values are valid.
|
||||||
PRPackedBool mMetadataValid;
|
PRPackedBool mMetadataValid;
|
||||||
|
|
||||||
|
// True if an event to notify about a change in the playback position has
|
||||||
|
// been queued, but not yet run. It is set to false when the event is
|
||||||
|
// run. This allows coalescing of these events as they can be produced
|
||||||
|
// many times per second.
|
||||||
|
PRPackedBool mPositionChangeQueued;
|
||||||
};
|
};
|
||||||
|
|
||||||
nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
|
nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
|
||||||
|
@ -350,9 +361,8 @@ nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* a
|
||||||
: mDecoder(aDecoder),
|
: mDecoder(aDecoder),
|
||||||
mStream(aStream),
|
mStream(aStream),
|
||||||
mBufferingWait(aBufferWaitTime),
|
mBufferingWait(aBufferWaitTime),
|
||||||
mBufferingBytes(0),
|
|
||||||
mBufferingStart(0),
|
mBufferingStart(0),
|
||||||
mAudioBufferSize(0),
|
mBufferingEndOffset(0),
|
||||||
mSampleRate(0),
|
mSampleRate(0),
|
||||||
mChannels(0),
|
mChannels(0),
|
||||||
mSampleSize(0),
|
mSampleSize(0),
|
||||||
|
@ -366,10 +376,10 @@ nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* a
|
||||||
mDownloadPosition(0),
|
mDownloadPosition(0),
|
||||||
mPlaybackPosition(0),
|
mPlaybackPosition(0),
|
||||||
mInitialVolume(aInitialVolume),
|
mInitialVolume(aInitialVolume),
|
||||||
mTimeOffset(0.0),
|
mTimeOffset(0),
|
||||||
mExpectMoreData(PR_TRUE),
|
|
||||||
mSeekTime(0.0),
|
mSeekTime(0.0),
|
||||||
mMetadataValid(PR_FALSE)
|
mMetadataValid(PR_FALSE),
|
||||||
|
mPositionChangeQueued(PR_FALSE)
|
||||||
{
|
{
|
||||||
mMonitor = nsAutoMonitor::NewMonitor("nsWaveStateMachine");
|
mMonitor = nsAutoMonitor::NewMonitor("nsWaveStateMachine");
|
||||||
mDownloadStatistics.Start(PR_IntervalNow());
|
mDownloadStatistics.Start(PR_IntervalNow());
|
||||||
|
@ -449,14 +459,7 @@ nsWaveStateMachine::GetDuration()
|
||||||
{
|
{
|
||||||
nsAutoMonitor monitor(mMonitor);
|
nsAutoMonitor monitor(mMonitor);
|
||||||
if (mMetadataValid) {
|
if (mMetadataValid) {
|
||||||
PRUint32 length = mWaveLength;
|
return BytesToTime(GetDataLength());
|
||||||
// If the decoder has a valid content length, and it's shorter than the
|
|
||||||
// expected length of the PCM data, calculate the playback duration from
|
|
||||||
// the content length rather than the expected PCM data length.
|
|
||||||
if (mTotalBytes >= 0 && mTotalBytes - mWavePCMOffset < length) {
|
|
||||||
length = mTotalBytes - mWavePCMOffset;
|
|
||||||
}
|
|
||||||
return BytesToTime(length);
|
|
||||||
}
|
}
|
||||||
return std::numeric_limits<float>::quiet_NaN();
|
return std::numeric_limits<float>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
@ -465,11 +468,10 @@ float
|
||||||
nsWaveStateMachine::GetCurrentTime()
|
nsWaveStateMachine::GetCurrentTime()
|
||||||
{
|
{
|
||||||
nsAutoMonitor monitor(mMonitor);
|
nsAutoMonitor monitor(mMonitor);
|
||||||
double time = 0.0;
|
if (mMetadataValid) {
|
||||||
if (mAudioStream) {
|
return BytesToTime(mTimeOffset);
|
||||||
time = mAudioStream->GetTime();
|
|
||||||
}
|
}
|
||||||
return float(time + mTimeOffset);
|
return std::numeric_limits<float>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -486,30 +488,25 @@ nsWaveStateMachine::IsEnded()
|
||||||
return mState == STATE_ENDED || mState == STATE_SHUTDOWN;
|
return mState == STATE_ENDED || mState == STATE_SHUTDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsWaveStateMachine::StreamEnded(PRBool aAtEnd)
|
|
||||||
{
|
|
||||||
nsAutoMonitor monitor(mMonitor);
|
|
||||||
mExpectMoreData = PR_FALSE;
|
|
||||||
|
|
||||||
// If we know the content length, set the bytes downloaded to this
|
|
||||||
// so the final progress event gets the correct final value.
|
|
||||||
if (mTotalBytes >= 0) {
|
|
||||||
mDownloadPosition = mTotalBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsHTMLMediaElement::NextFrameStatus
|
nsHTMLMediaElement::NextFrameStatus
|
||||||
nsWaveStateMachine::GetNextFrameStatus()
|
nsWaveStateMachine::GetNextFrameStatus()
|
||||||
{
|
{
|
||||||
nsAutoMonitor monitor(mMonitor);
|
nsAutoMonitor monitor(mMonitor);
|
||||||
if (mPlaybackPosition < mDownloadPosition)
|
|
||||||
return nsHTMLMediaElement::NEXT_FRAME_AVAILABLE;
|
|
||||||
if (mState == STATE_BUFFERING)
|
if (mState == STATE_BUFFERING)
|
||||||
return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING;
|
return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE_BUFFERING;
|
||||||
|
if (mPlaybackPosition < mDownloadPosition)
|
||||||
|
return nsHTMLMediaElement::NEXT_FRAME_AVAILABLE;
|
||||||
return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE;
|
return nsHTMLMediaElement::NEXT_FRAME_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
nsWaveStateMachine::GetTimeForPositionChange()
|
||||||
|
{
|
||||||
|
nsAutoMonitor monitor(mMonitor);
|
||||||
|
mPositionChangeQueued = PR_FALSE;
|
||||||
|
return GetCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsWaveStateMachine::Run()
|
nsWaveStateMachine::Run()
|
||||||
{
|
{
|
||||||
|
@ -552,10 +549,12 @@ nsWaveStateMachine::Run()
|
||||||
case STATE_BUFFERING: {
|
case STATE_BUFFERING: {
|
||||||
PRIntervalTime now = PR_IntervalNow();
|
PRIntervalTime now = PR_IntervalNow();
|
||||||
if ((PR_IntervalToMilliseconds(now - mBufferingStart) < mBufferingWait) &&
|
if ((PR_IntervalToMilliseconds(now - mBufferingStart) < mBufferingWait) &&
|
||||||
mStream->Available() < mBufferingBytes) {
|
mDownloadPosition < mBufferingEndOffset &&
|
||||||
LOG(PR_LOG_DEBUG, ("Buffering data until %d bytes or %d milliseconds\n",
|
(mTotalBytes < 0 || mDownloadPosition < mTotalBytes)) {
|
||||||
mBufferingBytes - mStream->Available(),
|
LOG(PR_LOG_DEBUG,
|
||||||
mBufferingWait - (now - mBufferingStart)));
|
("In buffering: buffering data until %d bytes available or %d milliseconds\n",
|
||||||
|
PRUint32(mBufferingEndOffset - mDownloadPosition),
|
||||||
|
mBufferingWait - (PR_IntervalToMilliseconds(now - mBufferingStart))));
|
||||||
monitor.Wait(PR_MillisecondsToInterval(1000));
|
monitor.Wait(PR_MillisecondsToInterval(1000));
|
||||||
} else {
|
} else {
|
||||||
ChangeState(mNextState);
|
ChangeState(mNextState);
|
||||||
|
@ -570,86 +569,102 @@ nsWaveStateMachine::Run()
|
||||||
case STATE_PLAYING: {
|
case STATE_PLAYING: {
|
||||||
if (!mAudioStream) {
|
if (!mAudioStream) {
|
||||||
OpenAudioStream();
|
OpenAudioStream();
|
||||||
} else {
|
if (!mAudioStream) {
|
||||||
mAudioStream->Resume();
|
mState = STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mStream->Available() < mSampleSize) {
|
PRUint32 startTime = PR_IntervalToMilliseconds(PR_IntervalNow());
|
||||||
if (mExpectMoreData) {
|
startTime -= AUDIO_BUFFER_LENGTH;
|
||||||
// Buffer until mBufferingWait milliseconds of data is available.
|
PRIntervalTime lastWakeup = PR_MillisecondsToInterval(startTime);
|
||||||
mBufferingBytes = TimeToBytes(float(mBufferingWait) / 1000.0);
|
|
||||||
mBufferingStart = PR_IntervalNow();
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> event =
|
do {
|
||||||
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, UpdateReadyStateForData);
|
PRIntervalTime now = PR_IntervalNow();
|
||||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
PRInt32 sleepTime = PR_IntervalToMilliseconds(now - lastWakeup);
|
||||||
|
lastWakeup = now;
|
||||||
|
|
||||||
ChangeState(STATE_BUFFERING);
|
// We aim to have AUDIO_BUFFER_LENGTH milliseconds of audio
|
||||||
} else {
|
// buffered, but only sleep for AUDIO_BUFFER_WAKEUP milliseconds
|
||||||
// Media stream has ended and there is less data available than a
|
// (waking early to refill before the backend underruns). Since we
|
||||||
// single sample so end playback.
|
// wake early, we only buffer sleepTime milliseconds of audio since
|
||||||
|
// there is still AUDIO_BUFFER_LENGTH - sleepTime milliseconds of
|
||||||
|
// audio buffered.
|
||||||
|
PRInt32 targetTime = AUDIO_BUFFER_LENGTH;
|
||||||
|
if (sleepTime < targetTime) {
|
||||||
|
targetTime = sleepTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt64 len = TimeToBytes(float(targetTime) / 1000.0f);
|
||||||
|
|
||||||
|
PRInt64 leftToPlay = GetDataLength() - mTimeOffset;
|
||||||
|
if (leftToPlay <= len) {
|
||||||
|
len = leftToPlay;
|
||||||
ChangeState(STATE_ENDED);
|
ChangeState(STATE_ENDED);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Assuming enough data is available from the network, we aim to
|
PRInt64 available = mDownloadPosition - mPlaybackPosition;
|
||||||
// completely fill the audio backend's buffers with data. This
|
|
||||||
// allows us plenty of time to wake up and refill the buffers
|
// don't buffer if we're at the end of the stream
|
||||||
// without an underrun occurring.
|
if (mState != STATE_ENDED && available < len) {
|
||||||
PRUint32 sampleSize = mSampleFormat == nsAudioStream::FORMAT_U8 ? 1 : 2;
|
mBufferingStart = PR_IntervalNow();
|
||||||
PRUint32 len = RoundDownToSample(NS_MIN(mStream->Available(),
|
mBufferingEndOffset = mDownloadPosition + TimeToBytes(float(mBufferingWait) / 1000.0f);
|
||||||
PRUint32(mAudioStream->Available() * sampleSize)));
|
mNextState = mState;
|
||||||
if (len) {
|
ChangeState(STATE_BUFFERING);
|
||||||
nsAutoArrayPtr<char> buf(new char[len]);
|
|
||||||
PRUint32 got = 0;
|
nsCOMPtr<nsIRunnable> event =
|
||||||
|
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, UpdateReadyStateForData);
|
||||||
|
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
nsAutoArrayPtr<char> buf(new char[size_t(len)]);
|
||||||
|
PRInt64 got = 0;
|
||||||
|
|
||||||
monitor.Exit();
|
monitor.Exit();
|
||||||
if (NS_FAILED(mStream->Read(buf.get(), len, &got))) {
|
PRBool ok = ReadAll(buf.get(), len, &got);
|
||||||
NS_WARNING("Stream read failed");
|
PRInt64 streamPos = mStream->Tell();
|
||||||
}
|
monitor.Enter();
|
||||||
|
|
||||||
if (got == 0) {
|
// Reached EOF.
|
||||||
|
if (!ok) {
|
||||||
ChangeState(STATE_ENDED);
|
ChangeState(STATE_ENDED);
|
||||||
|
if (got == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got less data than requested, go ahead and write what we
|
|
||||||
// got to the audio hardware. It's unlikely that this can happen
|
|
||||||
// since we never attempt to read more data than what is already
|
|
||||||
// buffered.
|
|
||||||
len = RoundDownToSample(got);
|
|
||||||
|
|
||||||
// Calculate difference between the current media stream position
|
// Calculate difference between the current media stream position
|
||||||
// and the expected end of the PCM data.
|
// and the expected end of the PCM data.
|
||||||
PRInt64 endDelta = mWavePCMOffset + mWaveLength - mStream->Tell();
|
PRInt64 endDelta = mWavePCMOffset + mWaveLength - streamPos;
|
||||||
if (endDelta < 0) {
|
if (endDelta < 0) {
|
||||||
// Read past the end of PCM data. Adjust len to avoid playing
|
// Read past the end of PCM data. Adjust got to avoid playing
|
||||||
// back trailing data.
|
// back trailing data.
|
||||||
len -= -endDelta;
|
got -= -endDelta;
|
||||||
if (RoundDownToSample(len) != len) {
|
|
||||||
NS_WARNING("PCM data does not end with complete sample");
|
|
||||||
len = RoundDownToSample(len);
|
|
||||||
}
|
|
||||||
ChangeState(STATE_ENDED);
|
ChangeState(STATE_ENDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32 lengthInSamples = len;
|
if (mState == STATE_ENDED) {
|
||||||
if (mSampleFormat == nsAudioStream::FORMAT_S16_LE) {
|
got = RoundDownToSample(got);
|
||||||
lengthInSamples /= sizeof(short);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRUint32 sampleSize = mSampleFormat == nsAudioStream::FORMAT_U8 ? 1 : 2;
|
||||||
|
NS_ABORT_IF_FALSE(got % sampleSize == 0, "Must write complete samples");
|
||||||
|
PRUint32 lengthInSamples = got / sampleSize;
|
||||||
|
|
||||||
|
monitor.Exit();
|
||||||
mAudioStream->Write(buf.get(), lengthInSamples);
|
mAudioStream->Write(buf.get(), lengthInSamples);
|
||||||
monitor.Enter();
|
monitor.Enter();
|
||||||
|
|
||||||
|
mTimeOffset += got;
|
||||||
|
FirePositionChanged(PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// To avoid waking up too frequently to top up these buffers,
|
if (mState == STATE_PLAYING) {
|
||||||
// calculate the duration of the currently buffered data and sleep
|
monitor.Wait(PR_MillisecondsToInterval(AUDIO_BUFFER_WAKEUP));
|
||||||
// until most of the buffered data has been consumed. We can't
|
}
|
||||||
// sleep for the entire duration because we might not wake up in
|
} while (mState == STATE_PLAYING);
|
||||||
// time to refill the buffers, causing an underrun. To avoid this,
|
|
||||||
// wake up when approximately half the buffered data has been
|
|
||||||
// consumed. This could be made smarter, but at least avoids waking
|
|
||||||
// up frequently to perform small buffer refills.
|
|
||||||
float nextWakeup = BytesToTime(mAudioBufferSize - mAudioStream->Available() * sizeof(short)) * 1000.0 / 2.0;
|
|
||||||
monitor.Wait(PR_MillisecondsToInterval(PRUint32(nextWakeup)));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,7 +687,9 @@ nsWaveStateMachine::Run()
|
||||||
|
|
||||||
// Calculate relative offset within PCM data.
|
// Calculate relative offset within PCM data.
|
||||||
PRInt64 position = RoundDownToSample(TimeToBytes(seekTime));
|
PRInt64 position = RoundDownToSample(TimeToBytes(seekTime));
|
||||||
NS_ABORT_IF_FALSE(position >= 0 && position <= mWaveLength, "Invalid seek position");
|
NS_ABORT_IF_FALSE(position >= 0 && position <= GetDataLength(), "Invalid seek position");
|
||||||
|
|
||||||
|
mTimeOffset = position;
|
||||||
|
|
||||||
// If position==0, instead of seeking to position+mWavePCMOffset,
|
// If position==0, instead of seeking to position+mWavePCMOffset,
|
||||||
// we want to first seek to 0 before seeking to
|
// we want to first seek to 0 before seeking to
|
||||||
|
@ -704,12 +721,6 @@ nsWaveStateMachine::Run()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor.Exit();
|
|
||||||
nsCOMPtr<nsIRunnable> stopEvent =
|
|
||||||
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, SeekingStopped);
|
|
||||||
NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC);
|
|
||||||
monitor.Enter();
|
|
||||||
|
|
||||||
if (mState == STATE_SEEKING && mSeekTime == seekTime) {
|
if (mState == STATE_SEEKING && mSeekTime == seekTime) {
|
||||||
// Special case: if a seek was requested during metadata load,
|
// Special case: if a seek was requested during metadata load,
|
||||||
// mNextState will have been clobbered. This can only happen when
|
// mNextState will have been clobbered. This can only happen when
|
||||||
|
@ -722,29 +733,30 @@ nsWaveStateMachine::Run()
|
||||||
}
|
}
|
||||||
ChangeState(nextState);
|
ChangeState(nextState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FirePositionChanged(PR_TRUE);
|
||||||
|
|
||||||
|
monitor.Exit();
|
||||||
|
nsCOMPtr<nsIRunnable> stopEvent =
|
||||||
|
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, SeekingStopped);
|
||||||
|
NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC);
|
||||||
|
monitor.Enter();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_PAUSED:
|
case STATE_PAUSED:
|
||||||
if (mAudioStream) {
|
|
||||||
mAudioStream->Pause();
|
|
||||||
}
|
|
||||||
monitor.Wait();
|
monitor.Wait();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_ENDED:
|
case STATE_ENDED:
|
||||||
|
FirePositionChanged(PR_TRUE);
|
||||||
|
|
||||||
if (mAudioStream) {
|
if (mAudioStream) {
|
||||||
monitor.Exit();
|
monitor.Exit();
|
||||||
mAudioStream->Drain();
|
mAudioStream->Drain();
|
||||||
monitor.Enter();
|
monitor.Enter();
|
||||||
mTimeOffset += mAudioStream->GetTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispose the audio stream early (before SHUTDOWN) so that
|
|
||||||
// GetCurrentTime no longer attempts to query the audio backend for
|
|
||||||
// stream time.
|
|
||||||
CloseAudioStream();
|
|
||||||
|
|
||||||
if (mState != STATE_SHUTDOWN) {
|
if (mState != STATE_SHUTDOWN) {
|
||||||
nsCOMPtr<nsIRunnable> event =
|
nsCOMPtr<nsIRunnable> event =
|
||||||
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, PlaybackEnded);
|
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, PlaybackEnded);
|
||||||
|
@ -765,9 +777,6 @@ nsWaveStateMachine::Run()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_SHUTDOWN:
|
case STATE_SHUTDOWN:
|
||||||
if (mAudioStream) {
|
|
||||||
mTimeOffset += mAudioStream->GetTime();
|
|
||||||
}
|
|
||||||
CloseAudioStream();
|
CloseAudioStream();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -776,20 +785,61 @@ nsWaveStateMachine::Run()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#if defined(DEBUG)
|
||||||
nsWaveStateMachine::UpdateTimeOffset(float aTime)
|
static PRBool
|
||||||
|
IsValidStateTransition(State aStartState, State aEndState)
|
||||||
{
|
{
|
||||||
nsAutoMonitor monitor(mMonitor);
|
if (aEndState == STATE_SHUTDOWN) {
|
||||||
mTimeOffset = NS_MIN(aTime, GetDuration());
|
return PR_TRUE;
|
||||||
if (mTimeOffset < 0.0) {
|
|
||||||
mTimeOffset = 0.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aStartState == aEndState) {
|
||||||
|
LOG(PR_LOG_WARNING, ("Transition to current state requested"));
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (aStartState) {
|
||||||
|
case STATE_LOADING_METADATA:
|
||||||
|
if (aEndState == STATE_PLAYING || aEndState == STATE_SEEKING ||
|
||||||
|
aEndState == STATE_PAUSED || aEndState == STATE_ERROR)
|
||||||
|
return PR_TRUE;
|
||||||
|
break;
|
||||||
|
case STATE_BUFFERING:
|
||||||
|
if (aEndState == STATE_PLAYING || aEndState == STATE_PAUSED ||
|
||||||
|
aEndState == STATE_SEEKING)
|
||||||
|
return PR_TRUE;
|
||||||
|
break;
|
||||||
|
case STATE_PLAYING:
|
||||||
|
if (aEndState == STATE_BUFFERING || aEndState == STATE_SEEKING ||
|
||||||
|
aEndState == STATE_ENDED || aEndState == STATE_PAUSED)
|
||||||
|
return PR_TRUE;
|
||||||
|
break;
|
||||||
|
case STATE_SEEKING:
|
||||||
|
if (aEndState == STATE_PLAYING || aEndState == STATE_PAUSED)
|
||||||
|
return PR_TRUE;
|
||||||
|
break;
|
||||||
|
case STATE_PAUSED:
|
||||||
|
if (aEndState == STATE_PLAYING || aEndState == STATE_SEEKING)
|
||||||
|
return PR_TRUE;
|
||||||
|
break;
|
||||||
|
case STATE_ENDED:
|
||||||
|
case STATE_ERROR:
|
||||||
|
case STATE_SHUTDOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(PR_LOG_ERROR, ("Invalid state transition from %d to %d", aStartState, aEndState));
|
||||||
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWaveStateMachine::ChangeState(State aState)
|
nsWaveStateMachine::ChangeState(State aState)
|
||||||
{
|
{
|
||||||
nsAutoMonitor monitor(mMonitor);
|
nsAutoMonitor monitor(mMonitor);
|
||||||
|
#if defined(DEBUG)
|
||||||
|
NS_ABORT_IF_FALSE(IsValidStateTransition(mState, aState), "Invalid state transition");
|
||||||
|
#endif
|
||||||
mState = aState;
|
mState = aState;
|
||||||
monitor.NotifyAll();
|
monitor.NotifyAll();
|
||||||
}
|
}
|
||||||
|
@ -805,7 +855,6 @@ nsWaveStateMachine::OpenAudioStream()
|
||||||
"Attempting to initialize audio stream with invalid metadata");
|
"Attempting to initialize audio stream with invalid metadata");
|
||||||
mAudioStream->Init(mChannels, mSampleRate, mSampleFormat);
|
mAudioStream->Init(mChannels, mSampleRate, mSampleFormat);
|
||||||
mAudioStream->SetVolume(mInitialVolume);
|
mAudioStream->SetVolume(mInitialVolume);
|
||||||
mAudioBufferSize = mAudioStream->Available() * sizeof(short);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -835,7 +884,8 @@ nsWaveStateMachine::GetStatistics()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWaveStateMachine::SetTotalBytes(PRInt64 aBytes) {
|
nsWaveStateMachine::SetTotalBytes(PRInt64 aBytes)
|
||||||
|
{
|
||||||
nsAutoMonitor monitor(mMonitor);
|
nsAutoMonitor monitor(mMonitor);
|
||||||
mTotalBytes = aBytes;
|
mTotalBytes = aBytes;
|
||||||
}
|
}
|
||||||
|
@ -913,18 +963,25 @@ nsWaveStateMachine::IsShutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsWaveStateMachine::ReadAll(char* aBuf, PRUint32 aSize)
|
nsWaveStateMachine::ReadAll(char* aBuf, PRInt64 aSize, PRInt64* aBytesRead = nsnull)
|
||||||
{
|
{
|
||||||
PRUint32 got = 0;
|
PRUint32 got = 0;
|
||||||
|
if (aBytesRead) {
|
||||||
|
*aBytesRead = 0;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
PRUint32 read = 0;
|
PRUint32 read = 0;
|
||||||
if (NS_FAILED(mStream->Read(aBuf + got, aSize - got, &read))) {
|
if (NS_FAILED(mStream->Read(aBuf + got, aSize - got, &read))) {
|
||||||
NS_WARNING("Stream read failed");
|
NS_WARNING("Stream read failed");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
if (IsShutdown())
|
if (IsShutdown() || read == 0) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
}
|
||||||
got += read;
|
got += read;
|
||||||
|
if (aBytesRead) {
|
||||||
|
*aBytesRead = got;
|
||||||
|
}
|
||||||
} while (got != aSize);
|
} while (got != aSize);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -958,28 +1015,59 @@ nsWaveStateMachine::LoadRIFFChunk()
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsWaveStateMachine::ScanForwardUntil(PRUint32 aWantedChunk, PRUint32* aChunkSize)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aChunkSize);
|
||||||
|
*aChunkSize = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char chunkHeader[8];
|
||||||
|
const char* p = chunkHeader;
|
||||||
|
|
||||||
|
if (!ReadAll(chunkHeader, sizeof(chunkHeader))) {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRUint32 magic = ReadUint32BE(&p);
|
||||||
|
PRUint32 size = ReadUint32LE(&p);
|
||||||
|
|
||||||
|
if (magic == aWantedChunk) {
|
||||||
|
*aChunkSize = size;
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RIFF chunks are two-byte aligned, so round up if necessary.
|
||||||
|
size += size % 2;
|
||||||
|
|
||||||
|
nsAutoArrayPtr<char> chunk(new char[size]);
|
||||||
|
if (!ReadAll(chunk.get(), size)) {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsWaveStateMachine::LoadFormatChunk()
|
nsWaveStateMachine::LoadFormatChunk()
|
||||||
{
|
{
|
||||||
PRUint32 rate, channels, sampleSize, sampleFormat;
|
PRUint32 fmtSize, rate, channels, sampleSize, sampleFormat;
|
||||||
char waveFormat[WAVE_FORMAT_SIZE];
|
char waveFormat[WAVE_FORMAT_CHUNK_SIZE];
|
||||||
const char* p = waveFormat;
|
const char* p = waveFormat;
|
||||||
|
|
||||||
// RIFF chunks are always word (two byte) aligned.
|
// RIFF chunks are always word (two byte) aligned.
|
||||||
NS_ABORT_IF_FALSE(mStream->Tell() % 2 == 0,
|
NS_ABORT_IF_FALSE(mStream->Tell() % 2 == 0,
|
||||||
"LoadFormatChunk called with unaligned stream");
|
"LoadFormatChunk called with unaligned stream");
|
||||||
|
|
||||||
|
// The "format" chunk may not directly follow the "riff" chunk, so skip
|
||||||
|
// over any intermediate chunks.
|
||||||
|
if (!ScanForwardUntil(FRMT_CHUNK_MAGIC, &fmtSize)) {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ReadAll(waveFormat, sizeof(waveFormat))) {
|
if (!ReadAll(waveFormat, sizeof(waveFormat))) {
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReadUint32BE(&p) != FRMT_CHUNK_MAGIC) {
|
|
||||||
NS_WARNING("Expected format chunk");
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 fmtsize = ReadUint32LE(&p);
|
|
||||||
|
|
||||||
if (ReadUint16LE(&p) != WAVE_FORMAT_ENCODING_PCM) {
|
if (ReadUint16LE(&p) != WAVE_FORMAT_ENCODING_PCM) {
|
||||||
NS_WARNING("WAVE is not uncompressed PCM, compressed encodings are not supported");
|
NS_WARNING("WAVE is not uncompressed PCM, compressed encodings are not supported");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
@ -1000,7 +1088,7 @@ nsWaveStateMachine::LoadFormatChunk()
|
||||||
// extension size of 0 bytes. Be polite and handle this rather than
|
// extension size of 0 bytes. Be polite and handle this rather than
|
||||||
// considering the file invalid. This code skips any extension of the
|
// considering the file invalid. This code skips any extension of the
|
||||||
// "format" chunk.
|
// "format" chunk.
|
||||||
if (fmtsize > WAVE_FORMAT_CHUNK_SIZE) {
|
if (fmtSize > WAVE_FORMAT_CHUNK_SIZE) {
|
||||||
char extLength[2];
|
char extLength[2];
|
||||||
const char* p = extLength;
|
const char* p = extLength;
|
||||||
|
|
||||||
|
@ -1009,7 +1097,7 @@ nsWaveStateMachine::LoadFormatChunk()
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint16 extra = ReadUint16LE(&p);
|
PRUint16 extra = ReadUint16LE(&p);
|
||||||
if (fmtsize - (WAVE_FORMAT_CHUNK_SIZE + 2) != extra) {
|
if (fmtSize - (WAVE_FORMAT_CHUNK_SIZE + 2) != extra) {
|
||||||
NS_WARNING("Invalid extended format chunk size");
|
NS_WARNING("Invalid extended format chunk size");
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1062,33 +1150,8 @@ nsWaveStateMachine::FindDataOffset()
|
||||||
|
|
||||||
// The "data" chunk may not directly follow the "format" chunk, so skip
|
// The "data" chunk may not directly follow the "format" chunk, so skip
|
||||||
// over any intermediate chunks.
|
// over any intermediate chunks.
|
||||||
for (;;) {
|
if (!ScanForwardUntil(DATA_CHUNK_MAGIC, &length)) {
|
||||||
char chunkHeader[8];
|
return PR_FALSE;
|
||||||
const char* p = chunkHeader;
|
|
||||||
|
|
||||||
if (!ReadAll(chunkHeader, sizeof(chunkHeader))) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 magic = ReadUint32BE(&p);
|
|
||||||
|
|
||||||
if (magic == DATA_CHUNK_MAGIC) {
|
|
||||||
length = ReadUint32LE(&p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (magic == FRMT_CHUNK_MAGIC) {
|
|
||||||
LOG(PR_LOG_ERROR, ("Invalid WAVE: expected \"data\" chunk but found \"format\" chunk"));
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 size = ReadUint32LE(&p);
|
|
||||||
size += size % 2;
|
|
||||||
|
|
||||||
nsAutoArrayPtr<char> chunk(new char[size]);
|
|
||||||
if (!ReadAll(chunk.get(), size)) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = mStream->Tell();
|
offset = mStream->Tell();
|
||||||
|
@ -1108,12 +1171,41 @@ nsWaveStateMachine::FindDataOffset()
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRInt64
|
||||||
|
nsWaveStateMachine::GetDataLength()
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(mMetadataValid,
|
||||||
|
"Attempting to initialize audio stream with invalid metadata");
|
||||||
|
|
||||||
|
PRInt64 length = mWaveLength;
|
||||||
|
// If the decoder has a valid content length, and it's shorter than the
|
||||||
|
// expected length of the PCM data, calculate the playback duration from
|
||||||
|
// the content length rather than the expected PCM data length.
|
||||||
|
if (mTotalBytes >= 0 && mTotalBytes - mWavePCMOffset < length) {
|
||||||
|
length = mTotalBytes - mWavePCMOffset;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsWaveStateMachine::FirePositionChanged(PRBool aCoalesce)
|
||||||
|
{
|
||||||
|
if (aCoalesce && mPositionChangeQueued) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPositionChangeQueued = PR_TRUE;
|
||||||
|
nsCOMPtr<nsIRunnable> event = NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, PlaybackPositionChanged);
|
||||||
|
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsWaveDecoder, nsIObserver)
|
NS_IMPL_THREADSAFE_ISUPPORTS1(nsWaveDecoder, nsIObserver)
|
||||||
|
|
||||||
nsWaveDecoder::nsWaveDecoder()
|
nsWaveDecoder::nsWaveDecoder()
|
||||||
: mInitialVolume(1.0),
|
: mInitialVolume(1.0),
|
||||||
mStream(nsnull),
|
mStream(nsnull),
|
||||||
mTimeOffset(0.0),
|
mTimeOffset(0.0),
|
||||||
|
mCurrentTime(0.0),
|
||||||
mEndedCurrentTime(0.0),
|
mEndedCurrentTime(0.0),
|
||||||
mEndedDuration(std::numeric_limits<float>::quiet_NaN()),
|
mEndedDuration(std::numeric_limits<float>::quiet_NaN()),
|
||||||
mEnded(PR_FALSE),
|
mEnded(PR_FALSE),
|
||||||
|
@ -1149,10 +1241,7 @@ nsWaveDecoder::GetCurrentPrincipal()
|
||||||
float
|
float
|
||||||
nsWaveDecoder::GetCurrentTime()
|
nsWaveDecoder::GetCurrentTime()
|
||||||
{
|
{
|
||||||
if (mPlaybackStateMachine) {
|
return mCurrentTime;
|
||||||
return mPlaybackStateMachine->GetCurrentTime();
|
|
||||||
}
|
|
||||||
return mEndedCurrentTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -1352,10 +1441,6 @@ nsWaveDecoder::ResourceLoaded()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPlaybackStateMachine) {
|
|
||||||
mPlaybackStateMachine->StreamEnded(PR_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mResourceLoaded = PR_TRUE;
|
mResourceLoaded = PR_TRUE;
|
||||||
|
|
||||||
if (!mMetadataLoadedReported || mResourceLoadedReported)
|
if (!mMetadataLoadedReported || mResourceLoadedReported)
|
||||||
|
@ -1381,9 +1466,6 @@ nsWaveDecoder::NetworkError()
|
||||||
if (mElement) {
|
if (mElement) {
|
||||||
mElement->NetworkError();
|
mElement->NetworkError();
|
||||||
}
|
}
|
||||||
if (mPlaybackStateMachine) {
|
|
||||||
mPlaybackStateMachine->StreamEnded(PR_FALSE);
|
|
||||||
}
|
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1530,10 +1612,6 @@ nsWaveDecoder::SeekingStarted()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPlaybackStateMachine) {
|
|
||||||
mPlaybackStateMachine->UpdateTimeOffset(mTimeOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mElement) {
|
if (mElement) {
|
||||||
mElement->SeekStarted();
|
mElement->SeekStarted();
|
||||||
}
|
}
|
||||||
|
@ -1597,6 +1675,24 @@ nsWaveDecoder::MediaErrorDecode()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsWaveDecoder::PlaybackPositionChanged()
|
||||||
|
{
|
||||||
|
if (mShuttingDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float lastTime = mCurrentTime;
|
||||||
|
|
||||||
|
if (mPlaybackStateMachine) {
|
||||||
|
mCurrentTime = mPlaybackStateMachine->GetTimeForPositionChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mElement && lastTime != mCurrentTime) {
|
||||||
|
mElement->DispatchSimpleEvent(NS_LITERAL_STRING("timeupdate"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWaveDecoder::SetDuration(PRInt64 /* aDuration */)
|
nsWaveDecoder::SetDuration(PRInt64 /* aDuration */)
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,6 +77,7 @@ _TEST_FILES += \
|
||||||
test_error_on_404.html \
|
test_error_on_404.html \
|
||||||
test_onloadedmetadata.html \
|
test_onloadedmetadata.html \
|
||||||
test_load_coalescing.html \
|
test_load_coalescing.html \
|
||||||
|
test_play.html \
|
||||||
test_progress1.html \
|
test_progress1.html \
|
||||||
test_progress3.html \
|
test_progress3.html \
|
||||||
test_source.html \
|
test_source.html \
|
||||||
|
@ -99,9 +100,6 @@ _TEST_FILES += \
|
||||||
seek.ogv \
|
seek.ogv \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
#XXX: disabled for now, see bug 478868
|
|
||||||
# test_play.html \
|
|
||||||
|
|
||||||
ifneq ($(OS_ARCH),WINNT)
|
ifneq ($(OS_ARCH),WINNT)
|
||||||
# These tests are disabled on windows until we
|
# These tests are disabled on windows until we
|
||||||
# figure out the random failures. See bug 475369.
|
# figure out the random failures. See bug 475369.
|
||||||
|
|
|
@ -14,16 +14,27 @@ SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
var v = document.getElementById("v");
|
var v = document.getElementById("v");
|
||||||
|
|
||||||
var playEvents = ["play", "canplay", "playing", "canplaythrough"];
|
var tokens = {
|
||||||
|
0: ["play"],
|
||||||
|
"play": ["canplay"],
|
||||||
|
"canplay": ["playing"],
|
||||||
|
"playing": ["canplay", "canplaythrough"],
|
||||||
|
"canplaythrough": ["canplay", "canplaythrough"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var state = 0;
|
||||||
|
|
||||||
function gotPlayEvent(event) {
|
function gotPlayEvent(event) {
|
||||||
is(event.type, playEvents.shift(), "Check expected event");
|
ok(tokens[state].indexOf(event.type) >= 0, "Check expected event got " + event.type + " at " + state);
|
||||||
}
|
state = event.type;
|
||||||
for (var i = 0; i < playEvents.length; ++i) {
|
|
||||||
v.addEventListener(playEvents[i], gotPlayEvent, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
["play", "canplay", "playing", "canplaythrough"].forEach(function (e) {
|
||||||
|
v.addEventListener(e, gotPlayEvent, false);
|
||||||
|
});
|
||||||
|
|
||||||
function ended() {
|
function ended() {
|
||||||
is(playEvents.length, 0, "Undelivered event " + playEvents[0]);
|
is(state, "canplaythrough", "Last event should be canplaythrough");
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
v.addEventListener("ended", ended, false);
|
v.addEventListener("ended", ended, false);
|
||||||
|
|
|
@ -3812,8 +3812,8 @@ nsSVGElement::NumberInfo nsSVGFEConvolveMatrixElement::sNumberInfo[4] =
|
||||||
|
|
||||||
nsSVGElement::IntegerInfo nsSVGFEConvolveMatrixElement::sIntegerInfo[4] =
|
nsSVGElement::IntegerInfo nsSVGFEConvolveMatrixElement::sIntegerInfo[4] =
|
||||||
{
|
{
|
||||||
{ &nsGkAtoms::order, 0 },
|
{ &nsGkAtoms::order, 3 },
|
||||||
{ &nsGkAtoms::order, 0 },
|
{ &nsGkAtoms::order, 3 },
|
||||||
{ &nsGkAtoms::targetX, 0 },
|
{ &nsGkAtoms::targetX, 0 },
|
||||||
{ &nsGkAtoms::targetY, 0 }
|
{ &nsGkAtoms::targetY, 0 }
|
||||||
};
|
};
|
||||||
|
|
|
@ -202,6 +202,7 @@ nsSVGPreserveAspectRatio::SetBaseValueString(const nsAString &aValueAsString,
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimVal = mBaseVal = val;
|
mAnimVal = mBaseVal = val;
|
||||||
|
aSVGElement->DidChangePreserveAspectRatio(aDoSetAttr);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1292,7 +1292,7 @@ nsSVGSVGElement::GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsSVGViewBoxRect viewbox;
|
nsSVGViewBoxRect viewbox;
|
||||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) {
|
if (mViewBox.IsValid()) {
|
||||||
viewbox = mViewBox.GetAnimValue();
|
viewbox = mViewBox.GetAnimValue();
|
||||||
} else {
|
} else {
|
||||||
viewbox.x = viewbox.y = 0.0f;
|
viewbox.x = viewbox.y = 0.0f;
|
||||||
|
@ -1461,7 +1461,7 @@ nsSVGSVGElement::GetLength(PRUint8 aCtxType)
|
||||||
{
|
{
|
||||||
float h, w;
|
float h, w;
|
||||||
|
|
||||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) {
|
if (mViewBox.IsValid()) {
|
||||||
const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue();
|
const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue();
|
||||||
w = viewbox.width;
|
w = viewbox.width;
|
||||||
h = viewbox.height;
|
h = viewbox.height;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
* the Initial Developer. All Rights Reserved.
|
* the Initial Developer. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Jonathan Watt <jonathan.watt@strath.ac.uk> (original author)
|
* Craig Topper <craig.topper@gmail.com> (original author)
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -78,6 +78,7 @@ nsSVGViewBox::Init()
|
||||||
{
|
{
|
||||||
mBaseVal = nsSVGViewBoxRect();
|
mBaseVal = nsSVGViewBoxRect();
|
||||||
mAnimVal = nsnull;
|
mAnimVal = nsnull;
|
||||||
|
mHasBaseVal = PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsSVGViewBoxRect&
|
const nsSVGViewBoxRect&
|
||||||
|
@ -94,10 +95,8 @@ nsSVGViewBox::SetBaseValue(float aX, float aY, float aWidth, float aHeight,
|
||||||
nsSVGElement *aSVGElement, PRBool aDoSetAttr)
|
nsSVGElement *aSVGElement, PRBool aDoSetAttr)
|
||||||
{
|
{
|
||||||
mAnimVal = nsnull;
|
mAnimVal = nsnull;
|
||||||
mBaseVal.x = aX;
|
mBaseVal = nsSVGViewBoxRect(aX, aY, aWidth, aHeight);
|
||||||
mBaseVal.y = aY;
|
mHasBaseVal = PR_TRUE;
|
||||||
mBaseVal.width = aWidth;
|
|
||||||
mBaseVal.height = aHeight;
|
|
||||||
|
|
||||||
aSVGElement->DidChangeViewBox(aDoSetAttr);
|
aSVGElement->DidChangeViewBox(aDoSetAttr);
|
||||||
}
|
}
|
||||||
|
@ -128,11 +127,7 @@ nsSVGViewBox::SetBaseValueString(const nsAString& aValue,
|
||||||
// there was a parse error.
|
// there was a parse error.
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
mAnimVal = nsnull;
|
SetBaseValue(vals[0], vals[1], vals[2], vals[3], aSVGElement, aDoSetAttr);
|
||||||
mBaseVal.x = vals[0];
|
|
||||||
mBaseVal.y = vals[1];
|
|
||||||
mBaseVal.width = vals[2];
|
|
||||||
mBaseVal.height = vals[3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsMemory::Free(str);
|
nsMemory::Free(str);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
* the Initial Developer. All Rights Reserved.
|
* the Initial Developer. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Jonathan Watt <jonathan.watt@strath.ac.uk> (original author)
|
* Craig Topper <craig.topper@gmail.com> (original author)
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
@ -61,6 +61,10 @@ public:
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
// Used by element to tell if viewbox is defined
|
||||||
|
PRBool IsValid() const
|
||||||
|
{ return (mHasBaseVal || mAnimVal); }
|
||||||
|
|
||||||
const nsSVGViewBoxRect& GetBaseValue() const
|
const nsSVGViewBoxRect& GetBaseValue() const
|
||||||
{ return mBaseVal; }
|
{ return mBaseVal; }
|
||||||
void SetBaseValue(float aX, float aY, float aWidth, float aHeight,
|
void SetBaseValue(float aX, float aY, float aWidth, float aHeight,
|
||||||
|
@ -80,6 +84,7 @@ private:
|
||||||
|
|
||||||
nsSVGViewBoxRect mBaseVal;
|
nsSVGViewBoxRect mBaseVal;
|
||||||
nsAutoPtr<nsSVGViewBoxRect> mAnimVal;
|
nsAutoPtr<nsSVGViewBoxRect> mAnimVal;
|
||||||
|
PRPackedBool mHasBaseVal;
|
||||||
|
|
||||||
struct DOMBaseVal : public nsIDOMSVGRect
|
struct DOMBaseVal : public nsIDOMSVGRect
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Bug - Crash [@ PL_DHashTableOperate] with DOMNodeInserted event listener removing window and frameset contenteditable</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="content" src="data:text/html;charset=utf-8,%3Cscript%3E%0Awindow.addEventListener%28%27DOMNodeInserted%27%2C%20function%28%29%20%7Bwindow.frameElement.parentNode.removeChild%28window.frameElement%29%3B%7D%2C%20true%29%3B%0A%3C/script%3E%0A%3Cframeset%20contenteditable%3D%22true%22%3E"></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>testcase2 Bug 432114 – Crash [@ PL_DHashTableOperate] with DOMNodeInserted event listener removing window and frameset contenteditable</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="content" src="data:application/xhtml+xml;charset=utf-8,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%0A%3Cframeset%20contenteditable%3D%22true%22/%3E%0A%3Cscript%3E%0Afunction%20doExecCommand%28%29%7B%0Adocument.execCommand%28%27insertParagraph%27%2C%20false%2C%20%27%27%29%3B%0A%7D%0AsetTimeout%28doExecCommand%2C100%29%3B%0Awindow.addEventListener%28%27DOMNodeRemoved%27%2C%20function%28%29%20%7Bwindow.frameElement.parentNode.removeChild%28window.frameElement%29%3B%7D%2C%20true%29%3B%0A%3C/script%3E%0A%3C/html%3E" style="width:1000px;height: 200px;"></iframe>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,4 +1,6 @@
|
||||||
load 40929-1.html
|
load 40929-1.html
|
||||||
load 369126-1.html
|
load 369126-1.html
|
||||||
load 403574-1.xhtml
|
load 403574-1.xhtml
|
||||||
|
load 432114-1.html
|
||||||
|
load 432114-2.html
|
||||||
load 436900-1.html
|
load 436900-1.html
|
||||||
|
|
|
@ -590,18 +590,16 @@ nsWebShell::EnsureCommandHandler()
|
||||||
{
|
{
|
||||||
if (!mCommandManager)
|
if (!mCommandManager)
|
||||||
{
|
{
|
||||||
mCommandManager = do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
|
nsCOMPtr<nsPICommandUpdater> commandUpdater =
|
||||||
if (!mCommandManager) return NS_ERROR_OUT_OF_MEMORY;
|
do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
|
||||||
|
if (!commandUpdater) return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
nsCOMPtr<nsPICommandUpdater> commandUpdater = do_QueryInterface(mCommandManager);
|
nsCOMPtr<nsIDOMWindow> domWindow =
|
||||||
if (!commandUpdater) return NS_ERROR_FAILURE;
|
do_GetInterface(static_cast<nsIInterfaceRequestor *>(this));
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(static_cast<nsIInterfaceRequestor *>(this));
|
nsresult rv = commandUpdater->Init(domWindow);
|
||||||
#ifdef DEBUG
|
if (NS_SUCCEEDED(rv))
|
||||||
nsresult rv =
|
mCommandManager = do_QueryInterface(commandUpdater);
|
||||||
#endif
|
|
||||||
commandUpdater->Init(domWindow);
|
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Initting command manager failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
|
return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
|
||||||
|
|
|
@ -4344,7 +4344,7 @@ nsresult nsEditor::EndUpdateViewBatch()
|
||||||
// the reflows we caused will get processed before the invalidates.
|
// the reflows we caused will get processed before the invalidates.
|
||||||
if (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) {
|
if (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) {
|
||||||
updateFlag = NS_VMREFRESH_DEFERRED;
|
updateFlag = NS_VMREFRESH_DEFERRED;
|
||||||
} else {
|
} else if (presShell) {
|
||||||
// Flush out layout. Need to do this because if we have no invalidates
|
// Flush out layout. Need to do this because if we have no invalidates
|
||||||
// to flush the viewmanager code won't flush our reflow here, and we
|
// to flush the viewmanager code won't flush our reflow here, and we
|
||||||
// have selection code that does sync caret scrolling in this case.
|
// have selection code that does sync caret scrolling in this case.
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Testcase for bug 448329</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<iframe id="frame448329"></iframe>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function test448329(id,cmd) {
|
||||||
|
|
||||||
|
var elm = document.getElementById(id);
|
||||||
|
var doc = elm.contentDocument;
|
||||||
|
doc.designMode = "On";
|
||||||
|
|
||||||
|
var s = doc.defaultView.getSelection();
|
||||||
|
|
||||||
|
// Test document node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
var range = doc.createRange();
|
||||||
|
range.setStart(doc, 0);
|
||||||
|
range.setEnd(doc, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.queryCommandIndeterm(cmd);
|
||||||
|
|
||||||
|
// Test HTML node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(doc.documentElement, 0);
|
||||||
|
range.setEnd(doc.documentElement, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.queryCommandIndeterm(cmd);
|
||||||
|
|
||||||
|
// Test BODY node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
var body = doc.documentElement.childNodes[1];
|
||||||
|
range.setStart(body, 0);
|
||||||
|
range.setEnd(body, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.queryCommandIndeterm(cmd);
|
||||||
|
|
||||||
|
var text = doc.createTextNode("Hello Kitty");
|
||||||
|
body.insertBefore(text, null)
|
||||||
|
|
||||||
|
// Test TEXT node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(text, 0);
|
||||||
|
range.setEnd(text, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.queryCommandIndeterm(cmd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test448329("frame448329", "backcolor")
|
||||||
|
test448329("frame448329", "hilitecolor")
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Testcase for bug 448329</title>
|
||||||
|
<script>
|
||||||
|
function go() {
|
||||||
|
test("myFrame", "backcolor");
|
||||||
|
}
|
||||||
|
function test(id,cmd) {
|
||||||
|
var doc = document.getElementById(id).contentDocument;
|
||||||
|
doc.designMode = "On";
|
||||||
|
|
||||||
|
var s = doc.defaultView.getSelection();
|
||||||
|
s.removeAllRanges();
|
||||||
|
s.addRange(doc.createRange());
|
||||||
|
|
||||||
|
doc.queryCommandIndeterm(cmd);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="go()"><iframe id="myFrame"></iframe></body>
|
||||||
|
</html>
|
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Testcase #3 for bug 448329</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<iframe id="frame448329"></iframe>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function test448329(id,cmd,val) {
|
||||||
|
|
||||||
|
var elm = document.getElementById(id);
|
||||||
|
var doc = elm.contentDocument;
|
||||||
|
doc.designMode = "On";
|
||||||
|
|
||||||
|
var s = doc.defaultView.getSelection();
|
||||||
|
|
||||||
|
// Test document node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
var range = doc.createRange();
|
||||||
|
range.setStart(doc, 0);
|
||||||
|
range.setEnd(doc, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
// Test HTML node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(doc.documentElement, 0);
|
||||||
|
range.setEnd(doc.documentElement, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
// Test BODY node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
var body = doc.documentElement.childNodes[1];
|
||||||
|
range.setStart(body, 0);
|
||||||
|
range.setEnd(body, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
var text = doc.createTextNode("Hello Kitty");
|
||||||
|
body.insertBefore(text, null)
|
||||||
|
|
||||||
|
// Test TEXT node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(text, 0);
|
||||||
|
range.setEnd(text, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
// Test BODY[0,0] + TEXT node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(body, 0);
|
||||||
|
range.setEnd(body, 0);
|
||||||
|
s.addRange(range);
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(text, 0);
|
||||||
|
range.setEnd(text, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
// Test BODY[0,1] + TEXT node
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(body, 0);
|
||||||
|
range.setEnd(body, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(text, 0);
|
||||||
|
range.setEnd(text, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
// Test BODY[0,1] + TEXT node without a parent
|
||||||
|
if (s.rangeCount > 0)
|
||||||
|
s.removeAllRanges();
|
||||||
|
range = doc.createRange();
|
||||||
|
range.setStart(body, 0);
|
||||||
|
range.setEnd(body, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
range = doc.createRange();
|
||||||
|
text = doc.createTextNode("Hello Kitty"); // not in doc
|
||||||
|
range.setStart(text, 0);
|
||||||
|
range.setEnd(text, 1);
|
||||||
|
s.addRange(range);
|
||||||
|
doc.execCommand(cmd,false,val);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test448329("frame448329", "backcolor", "green")
|
||||||
|
test448329("frame448329", "hilitecolor", "green")
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -4,4 +4,7 @@ load 407074-1.html
|
||||||
load 407277-1.html
|
load 407277-1.html
|
||||||
load 420439.html
|
load 420439.html
|
||||||
load 428489-1.html
|
load 428489-1.html
|
||||||
|
load 448329-1.html
|
||||||
|
load 448329-2.html
|
||||||
|
load 448329-3.html
|
||||||
load 467647-1.html
|
load 467647-1.html
|
||||||
|
|
|
@ -843,6 +843,9 @@ nsHTMLCSSUtils::GetCSSPropertyAtom(nsCSSEditableProperty aProperty, nsIAtom ** a
|
||||||
case eCSSEditableProperty_width:
|
case eCSSEditableProperty_width:
|
||||||
*aAtom = nsEditProperty::cssWidth;
|
*aAtom = nsEditProperty::cssWidth;
|
||||||
break;
|
break;
|
||||||
|
case eCSSEditableProperty_NONE:
|
||||||
|
// intentionally empty
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1406,6 +1409,11 @@ nsHTMLCSSUtils::GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** a
|
||||||
nsresult res;
|
nsresult res;
|
||||||
res = node->GetNodeType(&type);
|
res = node->GetNodeType(&type);
|
||||||
if (NS_FAILED(res)) return res;
|
if (NS_FAILED(res)) return res;
|
||||||
|
|
||||||
|
if (nsIDOMNode::DOCUMENT_NODE == type) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
// loop until we find an element
|
// loop until we find an element
|
||||||
while (node && nsIDOMNode::ELEMENT_NODE != type) {
|
while (node && nsIDOMNode::ELEMENT_NODE != type) {
|
||||||
parentNode = node;
|
parentNode = node;
|
||||||
|
|
|
@ -2365,6 +2365,7 @@ nsHTMLEditor::GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor, P
|
||||||
PRInt32 offset;
|
PRInt32 offset;
|
||||||
res = GetStartNodeAndOffset(selection, address_of(parent), &offset);
|
res = GetStartNodeAndOffset(selection, address_of(parent), &offset);
|
||||||
if (NS_FAILED(res)) return res;
|
if (NS_FAILED(res)) return res;
|
||||||
|
if (!parent) return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
// is the selection collapsed?
|
// is the selection collapsed?
|
||||||
PRBool bCollapsed;
|
PRBool bCollapsed;
|
||||||
|
@ -2399,6 +2400,8 @@ nsHTMLEditor::GetCSSBackgroundColorState(PRBool *aMixed, nsAString &aOutColor, P
|
||||||
nsCOMPtr<nsIDOMNode> blockParent = nodeToExamine;
|
nsCOMPtr<nsIDOMNode> blockParent = nodeToExamine;
|
||||||
if (!isBlock) {
|
if (!isBlock) {
|
||||||
blockParent = GetBlockNodeParent(nodeToExamine);
|
blockParent = GetBlockNodeParent(nodeToExamine);
|
||||||
|
if (!blockParent)
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to not walk off onto the Document node
|
// Make sure to not walk off onto the Document node
|
||||||
|
@ -3613,12 +3616,6 @@ nsHTMLEditor::AddOverrideStyleSheet(const nsAString& aURL)
|
||||||
// (This checks if already exists)
|
// (This checks if already exists)
|
||||||
ps->AddOverrideStyleSheet(sheet);
|
ps->AddOverrideStyleSheet(sheet);
|
||||||
|
|
||||||
// Save doc pointer to be able to use nsIStyleSheet::SetEnabled()
|
|
||||||
nsIDocument *document = ps->GetDocument();
|
|
||||||
if (!document)
|
|
||||||
return NS_ERROR_NULL_POINTER;
|
|
||||||
sheet->SetOwningDocument(document);
|
|
||||||
|
|
||||||
ps->ReconstructStyleData();
|
ps->ReconstructStyleData();
|
||||||
|
|
||||||
// Save as the last-loaded sheet
|
// Save as the last-loaded sheet
|
||||||
|
@ -3684,10 +3681,14 @@ nsHTMLEditor::EnableStyleSheet(const nsAString &aURL, PRBool aEnable)
|
||||||
nsCOMPtr<nsIDOMStyleSheet> domSheet(do_QueryInterface(sheet));
|
nsCOMPtr<nsIDOMStyleSheet> domSheet(do_QueryInterface(sheet));
|
||||||
NS_ASSERTION(domSheet, "Sheet not implementing nsIDOMStyleSheet!");
|
NS_ASSERTION(domSheet, "Sheet not implementing nsIDOMStyleSheet!");
|
||||||
|
|
||||||
|
// Ensure the style sheet is owned by our document.
|
||||||
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocWeak);
|
||||||
|
rv = sheet->SetOwningDocument(doc);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return domSheet->SetDisabled(!aEnable);
|
return domSheet->SetDisabled(!aEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsHTMLEditor::EnableExistingStyleSheet(const nsAString &aURL)
|
nsHTMLEditor::EnableExistingStyleSheet(const nsAString &aURL)
|
||||||
{
|
{
|
||||||
|
@ -3698,6 +3699,11 @@ nsHTMLEditor::EnableExistingStyleSheet(const nsAString &aURL)
|
||||||
// Enable sheet if already loaded.
|
// Enable sheet if already loaded.
|
||||||
if (sheet)
|
if (sheet)
|
||||||
{
|
{
|
||||||
|
// Ensure the style sheet is owned by our document.
|
||||||
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocWeak);
|
||||||
|
rv = sheet->SetOwningDocument(doc);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMStyleSheet> domSheet(do_QueryInterface(sheet));
|
nsCOMPtr<nsIDOMStyleSheet> domSheet(do_QueryInterface(sheet));
|
||||||
NS_ASSERTION(domSheet, "Sheet not implementing nsIDOMStyleSheet!");
|
NS_ASSERTION(domSheet, "Sheet not implementing nsIDOMStyleSheet!");
|
||||||
|
|
||||||
|
|
|
@ -1482,9 +1482,7 @@ ChromeTooltipListener::sTooltipCallback(nsITimer *aTimer,
|
||||||
if (textFound) {
|
if (textFound) {
|
||||||
nsString tipText(tooltipText);
|
nsString tipText(tooltipText);
|
||||||
self->CreateAutoHideTimer();
|
self->CreateAutoHideTimer();
|
||||||
nsIntRect widgetDot(0, 0, 1, 1);
|
nsIntPoint screenDot = widget->WidgetToScreenOffset();
|
||||||
nsIntRect screenDot;
|
|
||||||
widget->WidgetToScreen(widgetDot, screenDot);
|
|
||||||
self->ShowTooltip (self->mMouseScreenX - screenDot.x,
|
self->ShowTooltip (self->mMouseScreenX - screenDot.x,
|
||||||
self->mMouseScreenY - screenDot.y,
|
self->mMouseScreenY - screenDot.y,
|
||||||
tipText);
|
tipText);
|
||||||
|
|
|
@ -111,6 +111,9 @@ struct nsIntPoint {
|
||||||
y -= aPoint.y;
|
y -= aPoint.y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
nsIntPoint operator-() const {
|
||||||
|
return nsIntPoint(-x, -y);
|
||||||
|
}
|
||||||
void MoveTo(PRInt32 aX, PRInt32 aY) {x = aX; y = aY;}
|
void MoveTo(PRInt32 aX, PRInt32 aY) {x = aX; y = aY;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -844,11 +844,8 @@ nsLayoutUtils::TranslateWidgetToView(nsPresContext* aPresContext,
|
||||||
if (fromRoot == toRoot) {
|
if (fromRoot == toRoot) {
|
||||||
widgetPoint = aPt + fromOffset - toOffset;
|
widgetPoint = aPt + fromOffset - toOffset;
|
||||||
} else {
|
} else {
|
||||||
nsIntRect widgetRect(0, 0, 0, 0);
|
nsIntPoint screenPoint = aWidget->WidgetToScreenOffset();
|
||||||
nsIntRect screenRect;
|
widgetPoint = aPt + screenPoint - viewWidget->WidgetToScreenOffset();
|
||||||
aWidget->WidgetToScreen(widgetRect, screenRect);
|
|
||||||
viewWidget->ScreenToWidget(screenRect, widgetRect);
|
|
||||||
widgetPoint = aPt + widgetRect.TopLeft();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPoint widgetAppUnits(aPresContext->DevPixelsToAppUnits(widgetPoint.x),
|
nsPoint widgetAppUnits(aPresContext->DevPixelsToAppUnits(widgetPoint.x),
|
||||||
|
|
|
@ -5383,11 +5383,12 @@ PresShell::Paint(nsIView* aView,
|
||||||
// background color as recorded in the prescontext is guaranteed to
|
// background color as recorded in the prescontext is guaranteed to
|
||||||
// be opaque.
|
// be opaque.
|
||||||
|
|
||||||
|
PRBool needTransparency = PR_FALSE;
|
||||||
nscolor backgroundColor = mPresContext->DefaultBackgroundColor();
|
nscolor backgroundColor = mPresContext->DefaultBackgroundColor();
|
||||||
for (nsIView *view = aView; view; view = view->GetParent()) {
|
for (nsIView *view = aView; view; view = view->GetParent()) {
|
||||||
if (view->HasWidget() &&
|
if (view->HasWidget() &&
|
||||||
view->GetWidget()->GetTransparencyMode() != eTransparencyOpaque) {
|
view->GetWidget()->GetTransparencyMode() != eTransparencyOpaque) {
|
||||||
backgroundColor = NS_RGBA(0,0,0,0);
|
needTransparency = PR_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5408,9 +5409,11 @@ PresShell::Paint(nsIView* aView,
|
||||||
// backstop colors.
|
// backstop colors.
|
||||||
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
|
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
backgroundColor = NS_ComposeColors(backgroundColor, viewDefaultColor);
|
if (!needTransparency) {
|
||||||
aRenderingContext->SetColor(backgroundColor);
|
backgroundColor = NS_ComposeColors(backgroundColor, viewDefaultColor);
|
||||||
aRenderingContext->FillRect(aDirtyRegion.GetBounds());
|
aRenderingContext->SetColor(backgroundColor);
|
||||||
|
aRenderingContext->FillRect(aDirtyRegion.GetBounds());
|
||||||
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5434,7 +5437,8 @@ PresShell::Paint(nsIView* aView,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion,
|
nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion,
|
||||||
backgroundColor);
|
needTransparency ? NS_RGBA(0,0,0,0)
|
||||||
|
: backgroundColor);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6043,9 +6047,8 @@ PresShell::AdjustContextMenuKeyEvent(nsMouseEvent* aEvent)
|
||||||
|
|
||||||
nsCOMPtr<nsIWidget> widget = popupFrame->GetWindow();
|
nsCOMPtr<nsIWidget> widget = popupFrame->GetWindow();
|
||||||
aEvent->widget = widget;
|
aEvent->widget = widget;
|
||||||
nsIntRect widgetRect(0, 0, 1, 1);
|
nsIntPoint widgetPoint = widget->WidgetToScreenOffset();
|
||||||
widget->WidgetToScreen(widgetRect, widgetRect);
|
aEvent->refPoint = itemFrame->GetScreenRect().BottomLeft() - widgetPoint;
|
||||||
aEvent->refPoint = itemFrame->GetScreenRect().BottomLeft() - widgetRect.TopLeft();
|
|
||||||
|
|
||||||
mCurrentEventContent = itemFrame->GetContent();
|
mCurrentEventContent = itemFrame->GetContent();
|
||||||
mCurrentEventFrame = itemFrame;
|
mCurrentEventFrame = itemFrame;
|
||||||
|
|
|
@ -3555,13 +3555,12 @@ nsRect nsIFrame::GetScreenRectInAppUnits() const
|
||||||
nsIWidget* widget = view->GetNearestWidget(&toWidgetOffset);
|
nsIWidget* widget = view->GetNearestWidget(&toWidgetOffset);
|
||||||
|
|
||||||
if (widget) {
|
if (widget) {
|
||||||
nsIntRect localRect(0,0,0,0), screenRect;
|
nsIntPoint screenPoint = widget->WidgetToScreenOffset();
|
||||||
widget->WidgetToScreen(localRect, screenRect);
|
|
||||||
|
|
||||||
retval = mRect;
|
retval = mRect;
|
||||||
retval.MoveTo(toViewOffset + toWidgetOffset);
|
retval.MoveTo(toViewOffset + toWidgetOffset);
|
||||||
retval.x += PresContext()->DevPixelsToAppUnits(screenRect.x);
|
retval.x += PresContext()->DevPixelsToAppUnits(screenPoint.x);
|
||||||
retval.y += PresContext()->DevPixelsToAppUnits(screenRect.y);
|
retval.y += PresContext()->DevPixelsToAppUnits(screenPoint.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3831,10 +3831,9 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
|
||||||
const nsMouseEvent& mouseEvent =
|
const nsMouseEvent& mouseEvent =
|
||||||
static_cast<const nsMouseEvent&>(anEvent);
|
static_cast<const nsMouseEvent&>(anEvent);
|
||||||
// Get reference point relative to screen:
|
// Get reference point relative to screen:
|
||||||
nsIntRect windowRect(anEvent.refPoint, nsIntSize(1, 1));
|
nsIntPoint rootPoint(-1,-1);
|
||||||
nsIntRect rootPoint(-1,-1,1,1);
|
|
||||||
if (widget)
|
if (widget)
|
||||||
widget->WidgetToScreen(windowRect, rootPoint);
|
rootPoint = anEvent.refPoint + widget->WidgetToScreenOffset();
|
||||||
#ifdef MOZ_WIDGET_GTK2
|
#ifdef MOZ_WIDGET_GTK2
|
||||||
Window root = GDK_ROOT_WINDOW();
|
Window root = GDK_ROOT_WINDOW();
|
||||||
#else
|
#else
|
||||||
|
@ -4739,14 +4738,7 @@ WindowRef nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
|
||||||
// use its native widget (an obj-c object) we have to go
|
// use its native widget (an obj-c object) we have to go
|
||||||
// from the widget's screen coordinates to its window coords
|
// from the widget's screen coordinates to its window coords
|
||||||
// instead of straight to window coords.
|
// instead of straight to window coords.
|
||||||
nsIntRect geckoBounds;
|
nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
|
||||||
mWidget->GetBounds(geckoBounds);
|
|
||||||
// we need a rect that is the entire *internal* rect, so the
|
|
||||||
// x and y coords are 0, width is the same.
|
|
||||||
geckoBounds.x = 0;
|
|
||||||
geckoBounds.y = 0;
|
|
||||||
nsIntRect geckoScreenCoords;
|
|
||||||
mWidget->WidgetToScreen(geckoBounds, geckoScreenCoords);
|
|
||||||
|
|
||||||
Rect windowRect;
|
Rect windowRect;
|
||||||
WindowRef window = (WindowRef)pluginPort->cgPort.window;
|
WindowRef window = (WindowRef)pluginPort->cgPort.window;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<filter id="convoluted_lime" x="0%" y="0%" width="100%" height="100%">
|
||||||
|
<feFlood flood-color="lime"/>
|
||||||
|
<feConvolveMatrix order="3" kernelMatrix="
|
||||||
|
0 0 0
|
||||||
|
0 1 0
|
||||||
|
0 0 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect x="30" y="30" width="97" height="60" filter="url(#convoluted_lime)"/>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 339 B |
|
@ -0,0 +1,18 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
|
||||||
|
<desc>
|
||||||
|
<html:p>When the 'order' attribute of feConvolveMatrix is
|
||||||
|
omitted the effect is the same as if the value "3" were given.
|
||||||
|
Per <html:a href="https://bugzilla.mozilla.org/show_bug.cgi?id=478570">Bug 478570</html:a>
|
||||||
|
discussion and linked spec errata.</html:p>
|
||||||
|
</desc>
|
||||||
|
<defs>
|
||||||
|
<filter id="convoluted_lime" x="0%" y="0%" width="100%" height="100%">
|
||||||
|
<feFlood flood-color="lime"/>
|
||||||
|
<feConvolveMatrix kernelMatrix="
|
||||||
|
0 0 0
|
||||||
|
0 1 0
|
||||||
|
0 0 0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect x="30" y="30" width="97" height="60" fill="red" filter="url(#convoluted_lime)"/>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 663 B |
|
@ -67,3 +67,4 @@ fails == filter-marked-line-01.svg pass.svg # bug 477704
|
||||||
== filter-patterned-rect-01.svg pass.svg
|
== filter-patterned-rect-01.svg pass.svg
|
||||||
== filter-patterned-rect-02.svg pass.svg
|
== filter-patterned-rect-02.svg pass.svg
|
||||||
|
|
||||||
|
== feConvolveMatrix-order-01.svg feConvolveMatrix-order-01-ref.svg
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
diff --git a/media/libsydneyaudio/src/sydney_audio_waveapi.c b/media/libsydneyaudio/src/sydney_audio_waveapi.c
|
||||||
|
--- a/media/libsydneyaudio/src/sydney_audio_waveapi.c
|
||||||
|
+++ b/media/libsydneyaudio/src/sydney_audio_waveapi.c
|
||||||
|
@@ -147,17 +147,17 @@ int sa_stream_create_pcm(sa_stream_t **s
|
||||||
|
if (format != SA_PCM_FORMAT_S16_NE) {
|
||||||
|
return SA_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode != SA_MODE_WRONLY) {
|
||||||
|
return SA_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((_s = (sa_stream_t*)malloc(sizeof(sa_stream_t))) == NULL) {
|
||||||
|
+ if ((_s = (sa_stream_t*)calloc(1, sizeof(sa_stream_t))) == NULL) {
|
||||||
|
return SA_ERROR_OOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
_s->rwMode = mode;
|
||||||
|
_s->format = format;
|
||||||
|
_s->rate = rate;
|
||||||
|
_s->channels = nchannels;
|
||||||
|
_s->deviceName = DEFAULT_DEVICE_NAME;
|
|
@ -9,3 +9,5 @@ The svn revision number used was r3827.
|
||||||
|
|
||||||
The patch from Annodex trac ticket #427 (http://trac.annodex.net/ticket/447)
|
The patch from Annodex trac ticket #427 (http://trac.annodex.net/ticket/447)
|
||||||
was applied to fix bug #469698.
|
was applied to fix bug #469698.
|
||||||
|
|
||||||
|
Also applied patch for bug 478299.
|
||||||
|
|
|
@ -152,7 +152,7 @@ int sa_stream_create_pcm(sa_stream_t **s,
|
||||||
return SA_ERROR_NOT_SUPPORTED;
|
return SA_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_s = (sa_stream_t*)malloc(sizeof(sa_stream_t))) == NULL) {
|
if ((_s = (sa_stream_t*)calloc(1, sizeof(sa_stream_t))) == NULL) {
|
||||||
return SA_ERROR_OOM;
|
return SA_ERROR_OOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,4 @@ cp $1/include/sydney_audio.h include/sydney_audio.h
|
||||||
cp $1/src/*.c src/
|
cp $1/src/*.c src/
|
||||||
cp $1/AUTHORS ./AUTHORS
|
cp $1/AUTHORS ./AUTHORS
|
||||||
patch -p3 < 469698_mac_stream_endian.patch
|
patch -p3 < 469698_mac_stream_endian.patch
|
||||||
|
patch -p3 < 478299_zeromem_sa_stream.patch
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
function correctSpelling()
|
function correctSpelling()
|
||||||
{
|
{
|
||||||
// Note that this code only runs if the page is requested using the
|
// Note that this code only runs if the page is requested using the
|
||||||
// URL containing the correct spelling - e.g. "about:licence".
|
// URL containing the correct spelling - i.e. "about:licence".
|
||||||
if (document.location.href.match("icence"))
|
if (document.location.href.match("icence"))
|
||||||
{
|
{
|
||||||
function acceptNode(node)
|
function acceptNode(node)
|
||||||
|
@ -172,10 +172,12 @@
|
||||||
<li><a href="about:license#jep">Java Embedding Plugin License</a></li>
|
<li><a href="about:license#jep">Java Embedding Plugin License</a></li>
|
||||||
<li><a href="about:license#jemalloc">jemalloc License</a></li>
|
<li><a href="about:license#jemalloc">jemalloc License</a></li>
|
||||||
<li><a href="about:license#hunspell-lt">Lithuanian Spellchecking Dictionary</a></li>
|
<li><a href="about:license#hunspell-lt">Lithuanian Spellchecking Dictionary</a></li>
|
||||||
|
<li><a href="about:license#littlecms">Little cms License</a></li>
|
||||||
<li><a href="about:license#openvision">OpenVision License</a></li>
|
<li><a href="about:license#openvision">OpenVision License</a></li>
|
||||||
<li><a href="about:license#xdg">Red Hat xdg_user_dir_lookup License</a></li>
|
<li><a href="about:license#xdg">Red Hat xdg_user_dir_lookup License</a></li>
|
||||||
<li><a href="about:license#hunspell-ru">Russian Spellchecking Dictionary</a></li>
|
<li><a href="about:license#hunspell-ru">Russian Spellchecking Dictionary</a></li>
|
||||||
<li><a href="about:license#sparkle">Sparkle License</a></li>
|
<li><a href="about:license#sparkle">Sparkle License</a></li>
|
||||||
|
<li><a href="about:license#sunsoft">SunSoft License</a></li>
|
||||||
<li><a href="about:license#ucal">University of California License</a></li>
|
<li><a href="about:license#ucal">University of California License</a></li>
|
||||||
<li><a href="about:license#hunspell-en-US">US English Spellchecking Dictionary</a></li>
|
<li><a href="about:license#hunspell-en-US">US English Spellchecking Dictionary</a></li>
|
||||||
<li><a href="about:license#xiph">Xiph.org Foundation License</a></li>
|
<li><a href="about:license#xiph">Xiph.org Foundation License</a></li>
|
||||||
|
@ -2142,92 +2144,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h1><a name="hunspell-en-US"></a>US English Spellchecking Dictionary</h1>
|
|
||||||
|
|
||||||
<p class="correctme">This license applies to certain files in the directory
|
|
||||||
<span class="path">extensions/spellcheck/locales/en-US/hunspell/</span>. (This
|
|
||||||
code only ships in some localized versions of this product.)</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
Different parts of the US English dictionary (SCOWL) are subject to the following licenses as
|
|
||||||
shown below. For additional details, sources, credits, and public domain references, see
|
|
||||||
<a href="http://mxr.mozilla.org/mozilla/source/extensions/spellcheck/locales/en-US/hunspell/README.txt?raw=1">README.txt</a>.
|
|
||||||
The collective work of the Spell Checking Oriented Word Lists (SCOWL) is under the
|
|
||||||
following copyright:
|
|
||||||
Copyright 2000-2007 by Kevin Atkinson
|
|
||||||
Permission to use, copy, modify, distribute and sell these word lists, the associated scripts,
|
|
||||||
the output created from the scripts, and its documentation for any purpose is hereby
|
|
||||||
granted without fee, provided that the above copyright notice appears in all copies and that
|
|
||||||
both that copyright notice and this permission notice appear in supporting documentation.
|
|
||||||
Kevin Atkinson makes no representations about the suitability of this array for any
|
|
||||||
purpose. It is provided "as is" without express or implied warranty.
|
|
||||||
The WordNet database is under the following copyright:
|
|
||||||
This software and database is being provided to you, the LICENSEE, by Princeton
|
|
||||||
University under the following license. By obtaining, using and/or copying this software
|
|
||||||
and database, you agree that you have read, understood, and will comply with these terms
|
|
||||||
and conditions:
|
|
||||||
Permission to use, copy, modify and distribute this software and database and its
|
|
||||||
documentation for any purpose and without fee or royalty is hereby granted, provided that
|
|
||||||
you agree to comply with the following copyright notice and statements, including the
|
|
||||||
disclaimer, and that the same appear on ALL copies of the software, database and
|
|
||||||
documentation, including modifications that you make for internal use or for distribution.
|
|
||||||
WordNet 1.6 Copyright 1997 by Princeton University. All rights reserved.
|
|
||||||
THIS SOFTWARE AND DATABASE IS PROVIDED "AS IS" AND PRINCETON UNIVERSITY
|
|
||||||
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
|
|
||||||
EXAMPLE, BUT NOT LIMITATION, PRINCETON UNIVERSITY MAKES NO
|
|
||||||
REPRESENTATIONS OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY
|
|
||||||
PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE, DATABASE OR
|
|
||||||
DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
|
|
||||||
TRADEMARKS OR OTHER RIGHTS.
|
|
||||||
The name of Princeton University or Princeton may not be used in advertising or publicity
|
|
||||||
pertaining to distribution of the software and/or database. Title to copyright in this
|
|
||||||
software, database and any associated documentation shall at all times remain with
|
|
||||||
Princeton University and LICENSEE agrees to preserve same.
|
|
||||||
|
|
||||||
The "UK Advanced Cryptics Dictionary" is under the following copyright:
|
|
||||||
Copyright (c) J Ross Beresford 1993-1999. All Rights Reserved.
|
|
||||||
The following restriction is placed on the use of this publication: if The UK Advanced
|
|
||||||
Cryptics Dictionary is used in a software package or redistributed in any form, the
|
|
||||||
copyright notice must be prominently displayed and the text of this document must be
|
|
||||||
included verbatim. There are no other restrictions: I would like to see the list distributed
|
|
||||||
as widely as possible.
|
|
||||||
|
|
||||||
Various parts are under the Ispell copyright:
|
|
||||||
Copyright 1993, Geoff Kuenning, Granada Hills, CA
|
|
||||||
All rights reserved. Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
|
||||||
conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
provided with the distribution.
|
|
||||||
3. All modifications to the source code must be clearly marked as such. Binary
|
|
||||||
redistributions based on modified source code must be clearly marked as modified
|
|
||||||
versions in the documentation and/or other materials provided with the distribution.
|
|
||||||
(clause 4 removed with permission from Geoff Kuenning)
|
|
||||||
5. The name of Geoff Kuenning may not be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS
|
|
||||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
Additional Contributors:
|
|
||||||
Alan Beale <biljir@pobox.com>
|
|
||||||
M Cooper <thegrendel@theriver.com>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h1><a name="expat"></a>Expat License</h1>
|
<h1><a name="expat"></a>Expat License</h1>
|
||||||
|
@ -2423,111 +2339,6 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h1><a name="openvision"></a>OpenVision License</h1>
|
|
||||||
|
|
||||||
<p class="correctme">This license applies to the file
|
|
||||||
<span class="path">extensions/auth/gssapi.h</span>.</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
Copyright 1993 by OpenVision Technologies, Inc.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, distribute, and sell this software
|
|
||||||
and its documentation for any purpose is hereby granted without fee,
|
|
||||||
provided that the above copyright notice appears in all copies and
|
|
||||||
that both that copyright notice and this permission notice appear in
|
|
||||||
supporting documentation, and that the name of OpenVision not be used
|
|
||||||
in advertising or publicity pertaining to distribution of the software
|
|
||||||
without specific, written prior permission. OpenVision makes no
|
|
||||||
representations about the suitability of this software for any
|
|
||||||
purpose. It is provided "as is" without express or implied warranty.
|
|
||||||
|
|
||||||
OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
|
||||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h1><a name="sparkle"></a>Sparkle License</h1>
|
|
||||||
|
|
||||||
<p class="correctme">This license applies to certain files in the directory
|
|
||||||
<span class="path">camino/sparkle/</span>. (This code only ships in the
|
|
||||||
in the Camino browser or products based on it.)</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
Copyright (c) 2006 Andy Matuschak
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h1><a name="ucal"></a>University of California License</h1>
|
|
||||||
|
|
||||||
<p class="correctme">This license applies to the following files or, in the case of
|
|
||||||
directories, certain files in those directories:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li class="path">dbm/</li>
|
|
||||||
<li class="path">db/mork/src/morkQuickSort.cpp</li>
|
|
||||||
<li class="path">xpcom/glue/nsQuickSort.cpp</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
Copyright (c) 1990, 1993
|
|
||||||
The Regents of the University of California. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
[3 Deleted as of 22nd July 1999; see
|
|
||||||
<a href="ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change">ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change</a>
|
|
||||||
for details]
|
|
||||||
4. Neither the name of the University nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGE.
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
@ -2570,6 +2381,67 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
SUCH DAMAGE.
|
SUCH DAMAGE.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1><a name="littlecms"></a>Little cms License</h1>
|
||||||
|
|
||||||
|
<p class="correctme">This license applies to certain files in the directory
|
||||||
|
<span class="path">modules/lcms/</span>.</p>
|
||||||
|
<pre>
|
||||||
|
Copyright (C) 1998-2007 Marti Maria
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so, subject
|
||||||
|
to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1><a name="openvision"></a>OpenVision License</h1>
|
||||||
|
|
||||||
|
<p class="correctme">This license applies to the file
|
||||||
|
<span class="path">extensions/auth/gssapi.h</span>.</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Copyright 1993 by OpenVision Technologies, Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software
|
||||||
|
and its documentation for any purpose is hereby granted without fee,
|
||||||
|
provided that the above copyright notice appears in all copies and
|
||||||
|
that both that copyright notice and this permission notice appear in
|
||||||
|
supporting documentation, and that the name of OpenVision not be used
|
||||||
|
in advertising or publicity pertaining to distribution of the software
|
||||||
|
without specific, written prior permission. OpenVision makes no
|
||||||
|
representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||||
|
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h1><a name="xdg"></a>Red Hat xdg_user_dir_lookup License</h1>
|
<h1><a name="xdg"></a>Red Hat xdg_user_dir_lookup License</h1>
|
||||||
|
@ -2641,6 +2513,217 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1><a name="sparkle"></a>Sparkle License</h1>
|
||||||
|
|
||||||
|
<p class="correctme">This license applies to certain files in the directory
|
||||||
|
<span class="path">camino/sparkle/</span>. (This code only ships in the
|
||||||
|
in the Camino browser or products based on it.)</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Copyright (c) 2006 Andy Matuschak
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1><a name="sunsoft"></a>SunSoft License</h1>
|
||||||
|
|
||||||
|
<p class="correctme">This license applies to the file
|
||||||
|
<span class="path">modules/lcms/include/icc34.h</span>.</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Copyright (c) 1994-1996 SunSoft, Inc.
|
||||||
|
|
||||||
|
Rights Reserved
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without restrict-
|
||||||
|
ion, including without limitation the rights to use, copy, modify,
|
||||||
|
merge, publish distribute, sublicense, and/or sell copies of the
|
||||||
|
Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
|
||||||
|
INFRINGEMENT. IN NO EVENT SHALL SUNSOFT, INC. OR ITS PARENT
|
||||||
|
COMPANY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of SunSoft, Inc.
|
||||||
|
shall not be used in advertising or otherwise to promote the
|
||||||
|
sale, use or other dealings in this Software without written
|
||||||
|
authorization from SunSoft Inc.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1><a name="ucal"></a>University of California License</h1>
|
||||||
|
|
||||||
|
<p class="correctme">This license applies to the following files or, in the case of
|
||||||
|
directories, certain files in those directories:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li class="path">dbm/</li>
|
||||||
|
<li class="path">db/mork/src/morkQuickSort.cpp</li>
|
||||||
|
<li class="path">xpcom/glue/nsQuickSort.cpp</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Copyright (c) 1990, 1993
|
||||||
|
The Regents of the University of California. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
[3 Deleted as of 22nd July 1999; see
|
||||||
|
<a href="ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change">ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change</a>
|
||||||
|
for details]
|
||||||
|
4. Neither the name of the University nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1><a name="hunspell-en-US"></a>US English Spellchecking Dictionary</h1>
|
||||||
|
|
||||||
|
<p class="correctme">This license applies to certain files in the directory
|
||||||
|
<span class="path">extensions/spellcheck/locales/en-US/hunspell/</span>. (This
|
||||||
|
code only ships in some localized versions of this product.)</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
Different parts of the US English dictionary (SCOWL) are subject to the following licenses as
|
||||||
|
shown below. For additional details, sources, credits, and public domain references, see
|
||||||
|
<a href="http://mxr.mozilla.org/mozilla/source/extensions/spellcheck/locales/en-US/hunspell/README.txt?raw=1">README.txt</a>.
|
||||||
|
|
||||||
|
The collective work of the Spell Checking Oriented Word Lists (SCOWL) is under the
|
||||||
|
following copyright:
|
||||||
|
|
||||||
|
Copyright 2000-2007 by Kevin Atkinson
|
||||||
|
Permission to use, copy, modify, distribute and sell these word lists, the associated scripts,
|
||||||
|
the output created from the scripts, and its documentation for any purpose is hereby
|
||||||
|
granted without fee, provided that the above copyright notice appears in all copies and that
|
||||||
|
both that copyright notice and this permission notice appear in supporting documentation.
|
||||||
|
Kevin Atkinson makes no representations about the suitability of this array for any
|
||||||
|
purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
The WordNet database is under the following copyright:
|
||||||
|
|
||||||
|
This software and database is being provided to you, the LICENSEE, by Princeton
|
||||||
|
University under the following license. By obtaining, using and/or copying this software
|
||||||
|
and database, you agree that you have read, understood, and will comply with these terms
|
||||||
|
and conditions:
|
||||||
|
Permission to use, copy, modify and distribute this software and database and its
|
||||||
|
documentation for any purpose and without fee or royalty is hereby granted, provided that
|
||||||
|
you agree to comply with the following copyright notice and statements, including the
|
||||||
|
disclaimer, and that the same appear on ALL copies of the software, database and
|
||||||
|
documentation, including modifications that you make for internal use or for distribution.
|
||||||
|
WordNet 1.6 Copyright 1997 by Princeton University. All rights reserved.
|
||||||
|
THIS SOFTWARE AND DATABASE IS PROVIDED "AS IS" AND PRINCETON UNIVERSITY
|
||||||
|
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
|
||||||
|
EXAMPLE, BUT NOT LIMITATION, PRINCETON UNIVERSITY MAKES NO
|
||||||
|
REPRESENTATIONS OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY
|
||||||
|
PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE, DATABASE OR
|
||||||
|
DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
|
||||||
|
TRADEMARKS OR OTHER RIGHTS.
|
||||||
|
The name of Princeton University or Princeton may not be used in advertising or publicity
|
||||||
|
pertaining to distribution of the software and/or database. Title to copyright in this
|
||||||
|
software, database and any associated documentation shall at all times remain with
|
||||||
|
Princeton University and LICENSEE agrees to preserve same.
|
||||||
|
|
||||||
|
The "UK Advanced Cryptics Dictionary" is under the following copyright:
|
||||||
|
|
||||||
|
Copyright (c) J Ross Beresford 1993-1999. All Rights Reserved.
|
||||||
|
The following restriction is placed on the use of this publication: if The UK Advanced
|
||||||
|
Cryptics Dictionary is used in a software package or redistributed in any form, the
|
||||||
|
copyright notice must be prominently displayed and the text of this document must be
|
||||||
|
included verbatim. There are no other restrictions: I would like to see the list distributed
|
||||||
|
as widely as possible.
|
||||||
|
|
||||||
|
Various parts are under the Ispell copyright:
|
||||||
|
|
||||||
|
Copyright 1993, Geoff Kuenning, Granada Hills, CA
|
||||||
|
All rights reserved. Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
provided with the distribution.
|
||||||
|
3. All modifications to the source code must be clearly marked as such. Binary
|
||||||
|
redistributions based on modified source code must be clearly marked as modified
|
||||||
|
versions in the documentation and/or other materials provided with the distribution.
|
||||||
|
(clause 4 removed with permission from Geoff Kuenning)
|
||||||
|
5. The name of Geoff Kuenning may not be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS
|
||||||
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Additional Contributors:
|
||||||
|
|
||||||
|
Alan Beale <biljir@pobox.com>
|
||||||
|
M Cooper <thegrendel@theriver.com>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h1><a name="xiph"></a>Xiph.org Foundation License</h1>
|
<h1><a name="xiph"></a>Xiph.org Foundation License</h1>
|
||||||
|
|
|
@ -373,10 +373,9 @@ nsIntRect nsView::CalcWidgetBounds(nsWindowType aType)
|
||||||
|
|
||||||
if (parentWidget && aType == eWindowType_popup &&
|
if (parentWidget && aType == eWindowType_popup &&
|
||||||
mVis == nsViewVisibility_kShow) {
|
mVis == nsViewVisibility_kShow) {
|
||||||
nsIntRect screenRect(0,0,1,1);
|
nsIntPoint screenPoint = parentWidget->WidgetToScreenOffset();
|
||||||
parentWidget->WidgetToScreen(screenRect, screenRect);
|
viewBounds += nsPoint(NSIntPixelsToAppUnits(screenPoint.x, p2a),
|
||||||
viewBounds += nsPoint(NSIntPixelsToAppUnits(screenRect.x, p2a),
|
NSIntPixelsToAppUnits(screenPoint.y, p2a));
|
||||||
NSIntPixelsToAppUnits(screenRect.y, p2a));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,21 +808,19 @@ nsPoint nsIView::GetOffsetTo(const nsIView* aOther) const
|
||||||
|
|
||||||
nsIntPoint nsIView::GetScreenPosition() const
|
nsIntPoint nsIView::GetScreenPosition() const
|
||||||
{
|
{
|
||||||
nsIntRect screenRect(0,0,0,0);
|
nsIntPoint screenPoint(0,0);
|
||||||
nsPoint toWidgetOffset(0,0);
|
nsPoint toWidgetOffset(0,0);
|
||||||
nsIWidget* widget = GetNearestWidget(&toWidgetOffset);
|
nsIWidget* widget = GetNearestWidget(&toWidgetOffset);
|
||||||
if (widget) {
|
if (widget) {
|
||||||
nsCOMPtr<nsIDeviceContext> dx;
|
nsCOMPtr<nsIDeviceContext> dx;
|
||||||
mViewManager->GetDeviceContext(*getter_AddRefs(dx));
|
mViewManager->GetDeviceContext(*getter_AddRefs(dx));
|
||||||
PRInt32 p2a = dx->AppUnitsPerDevPixel();
|
PRInt32 p2a = dx->AppUnitsPerDevPixel();
|
||||||
nsIntRect ourRect(NSAppUnitsToIntPixels(toWidgetOffset.x, p2a),
|
nsIntPoint ourPoint(NSAppUnitsToIntPixels(toWidgetOffset.x, p2a),
|
||||||
NSAppUnitsToIntPixels(toWidgetOffset.y, p2a),
|
NSAppUnitsToIntPixels(toWidgetOffset.y, p2a));
|
||||||
0,
|
screenPoint = ourPoint + widget->WidgetToScreenOffset();
|
||||||
0);
|
|
||||||
widget->WidgetToScreen(ourRect, screenRect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsIntPoint(screenRect.x, screenRect.y);
|
return screenPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIWidget* nsIView::GetNearestWidget(nsPoint* aOffset) const
|
nsIWidget* nsIView::GetNearestWidget(nsPoint* aOffset) const
|
||||||
|
|
|
@ -97,10 +97,10 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
|
||||||
#define NS_NATIVE_TSF_POINTER 100
|
#define NS_NATIVE_TSF_POINTER 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 075a7792-6ba9-454e-b431-25a43fdbd3f6
|
// 0dda48db-4f61-44a7-9f92-041cd92b8a9c
|
||||||
#define NS_IWIDGET_IID \
|
#define NS_IWIDGET_IID \
|
||||||
{ 0x075a7792, 0x6ba9, 0x454e, \
|
{ 0x0dda48db, 0x4f61, 0x44a7, \
|
||||||
{ 0xb4, 0x31, 0x25, 0xa4, 0x3f, 0xdb, 0xd3, 0xf6 } }
|
{ 0x9f, 0x92, 0x04, 0x1c, 0xd9, 0x2b, 0x8a, 0x9c } }
|
||||||
|
|
||||||
// Hide the native window systems real window type so as to avoid
|
// Hide the native window systems real window type so as to avoid
|
||||||
// including native window system types and APIs. This is necessary
|
// including native window system types and APIs. This is necessary
|
||||||
|
@ -901,22 +901,12 @@ class nsIWidget : public nsISupports {
|
||||||
NS_IMETHOD ShowMenuBar(PRBool aShow) = 0;
|
NS_IMETHOD ShowMenuBar(PRBool aShow) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert from this widget coordinates to screen coordinates.
|
* Return this widget's origin in screen coordinates.
|
||||||
*
|
*
|
||||||
* @param aOldRect widget coordinates stored in the x,y members
|
* @return screen coordinates stored in the x,y members
|
||||||
* @param aNewRect screen coordinates stored in the x,y members
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NS_IMETHOD WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect) = 0;
|
virtual nsIntPoint WidgetToScreenOffset() = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert from screen coordinates to this widget's coordinates.
|
|
||||||
*
|
|
||||||
* @param aOldRect screen coordinates stored in the x,y members
|
|
||||||
* @param aNewRect widget's coordinates stored in the x,y members
|
|
||||||
*/
|
|
||||||
|
|
||||||
NS_IMETHOD ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When adjustments are to made to a whole set of child widgets, call this
|
* When adjustments are to made to a whole set of child widgets, call this
|
||||||
|
|
|
@ -356,8 +356,7 @@ public:
|
||||||
virtual void* GetNativeData(PRUint32 aDataType);
|
virtual void* GetNativeData(PRUint32 aDataType);
|
||||||
NS_IMETHOD SetColorMap(nsColorMap *aColorMap);
|
NS_IMETHOD SetColorMap(nsColorMap *aColorMap);
|
||||||
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect);
|
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect);
|
||||||
NS_IMETHOD WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect);
|
virtual nsIntPoint WidgetToScreenOffset();
|
||||||
NS_IMETHOD ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect);
|
|
||||||
NS_IMETHOD BeginResizingChildren(void);
|
NS_IMETHOD BeginResizingChildren(void);
|
||||||
NS_IMETHOD EndResizingChildren(void);
|
NS_IMETHOD EndResizingChildren(void);
|
||||||
virtual PRBool ShowsResizeIndicator(nsIntRect* aResizerRect);
|
virtual PRBool ShowsResizeIndicator(nsIntRect* aResizerRect);
|
||||||
|
|
|
@ -2102,65 +2102,30 @@ PRBool nsChildView::PointInWidget(Point aThePoint)
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
|
||||||
// Convert the given rect to global coordinates.
|
// Return the offset between this child view and the screen.
|
||||||
// @param aLocalRect -- rect in local coordinates of this widget
|
// @return -- widget origin in screen coordinates
|
||||||
// @param aGlobalRect -- |aLocalRect| in global coordinates
|
nsIntPoint nsChildView::WidgetToScreenOffset()
|
||||||
NS_IMETHODIMP nsChildView::WidgetToScreen(const nsIntRect& aLocalRect, nsIntRect& aGlobalRect)
|
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||||
|
|
||||||
NSRect temp;
|
NSPoint temp;
|
||||||
GeckoRectToNSRect(aLocalRect, temp);
|
temp.x = 0;
|
||||||
|
temp.y = 0;
|
||||||
|
|
||||||
// 1. First translate this rect into window coords. The returned rect is always in
|
// 1. First translate this point into window coords. The returned point is always in
|
||||||
// bottom-left coordinates.
|
// bottom-left coordinates.
|
||||||
//
|
temp = [mView convertPoint:temp toView:nil];
|
||||||
// NOTE: convertRect:toView:nil doesn't care if |mView| is a flipped view (with
|
|
||||||
// top-left coords) and so assumes that our passed-in rect's origin is in
|
|
||||||
// bottom-left coordinates. We adjust this further down, by subtracting
|
|
||||||
// the final screen rect's origin by the rect's height, to get the origo
|
|
||||||
// where we want it.
|
|
||||||
temp = [mView convertRect:temp toView:nil];
|
|
||||||
|
|
||||||
// 2. We turn the window-coord rect's origin into screen (still bottom-left) coords.
|
// 2. We turn the window-coord rect's origin into screen (still bottom-left) coords.
|
||||||
temp.origin = [[mView nativeWindow] convertBaseToScreen:temp.origin];
|
temp = [[mView nativeWindow] convertBaseToScreen:temp];
|
||||||
|
|
||||||
// 3. Since we're dealing in bottom-left coords, we need to make it top-left coords
|
// 3. Since we're dealing in bottom-left coords, we need to make it top-left coords
|
||||||
// before we pass it back to Gecko.
|
// before we pass it back to Gecko.
|
||||||
FlipCocoaScreenCoordinate(temp.origin);
|
FlipCocoaScreenCoordinate(temp);
|
||||||
|
|
||||||
// 4. If this is rect has a size (and is not simply a point), it is important to account
|
return nsIntPoint(NSToIntRound(temp.x), NSToIntRound(temp.y));
|
||||||
// for the fact that convertRect:toView:nil thought our passed-in point was in bottom-left
|
|
||||||
// coords in step #1. Thus, we subtract the rect's height, to get the top-left rect's origin
|
|
||||||
// where we want it.
|
|
||||||
temp.origin.y -= temp.size.height;
|
|
||||||
|
|
||||||
NSRectToGeckoRect(temp, aGlobalRect);
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nsIntPoint(0,0));
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Convert the given rect to local coordinates.
|
|
||||||
// @param aGlobalRect -- rect in screen coordinates
|
|
||||||
// @param aLocalRect -- |aGlobalRect| in coordinates of this widget
|
|
||||||
NS_IMETHODIMP nsChildView::ScreenToWidget(const nsIntRect& aGlobalRect, nsIntRect& aLocalRect)
|
|
||||||
{
|
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
||||||
|
|
||||||
NSRect temp;
|
|
||||||
GeckoRectToNSRect(aGlobalRect, temp);
|
|
||||||
FlipCocoaScreenCoordinate(temp.origin);
|
|
||||||
|
|
||||||
temp.origin = [[mView nativeWindow] convertScreenToBase:temp.origin]; // convert to screen coords
|
|
||||||
temp = [mView convertRect:temp fromView:nil]; // convert to window coords
|
|
||||||
|
|
||||||
NSRectToGeckoRect(temp, aLocalRect);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -222,8 +222,7 @@ public:
|
||||||
NS_IMETHOD SetMenuBar(void* aMenuBar);
|
NS_IMETHOD SetMenuBar(void* aMenuBar);
|
||||||
virtual nsMenuBarX* GetMenuBar();
|
virtual nsMenuBarX* GetMenuBar();
|
||||||
NS_IMETHOD ShowMenuBar(PRBool aShow);
|
NS_IMETHOD ShowMenuBar(PRBool aShow);
|
||||||
NS_IMETHOD WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect);
|
virtual nsIntPoint WidgetToScreenOffset();
|
||||||
NS_IMETHOD ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect);
|
|
||||||
|
|
||||||
virtual void* GetNativeData(PRUint32 aDataType) ;
|
virtual void* GetNativeData(PRUint32 aDataType) ;
|
||||||
|
|
||||||
|
|
|
@ -1221,37 +1221,15 @@ NS_IMETHODIMP nsCocoaWindow::ShowMenuBar(PRBool aShow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsCocoaWindow::WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
nsIntPoint nsCocoaWindow::WidgetToScreenOffset()
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||||
|
|
||||||
nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect([mWindow contentRectForFrameRect:[mWindow frame]]);
|
nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect([mWindow contentRectForFrameRect:[mWindow frame]]);
|
||||||
|
|
||||||
aNewRect.x = r.x + aOldRect.x;
|
return r.TopLeft();
|
||||||
aNewRect.y = r.y + aOldRect.y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
|
|
||||||
return NS_OK;
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nsIntPoint(0,0));
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsCocoaWindow::ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
|
||||||
{
|
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
||||||
|
|
||||||
nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect([mWindow contentRectForFrameRect:[mWindow frame]]);
|
|
||||||
|
|
||||||
aNewRect.x = aOldRect.x - r.x;
|
|
||||||
aNewRect.y = aOldRect.y - r.y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1354,8 +1354,7 @@ nsWindow::SetFocus(PRBool aRaise)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsWindow::GetScreenBounds(nsIntRect &aRect)
|
nsWindow::GetScreenBounds(nsIntRect &aRect)
|
||||||
{
|
{
|
||||||
nsIntRect origin(0, 0, mBounds.width, mBounds.height);
|
aRect = nsIntRect(WidgetToScreenOffset(), mBounds.Size());
|
||||||
WidgetToScreen(origin, aRect);
|
|
||||||
LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
|
LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
|
||||||
aRect.x, aRect.y,
|
aRect.x, aRect.y,
|
||||||
mBounds.width, mBounds.height,
|
mBounds.width, mBounds.height,
|
||||||
|
@ -1857,48 +1856,22 @@ nsWindow::ShowMenuBar(PRBool aShow)
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsIntPoint
|
||||||
nsWindow::WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
nsWindow::WidgetToScreenOffset()
|
||||||
{
|
{
|
||||||
gint x = 0, y = 0;
|
gint x = 0, y = 0;
|
||||||
|
|
||||||
if (mContainer) {
|
if (mContainer) {
|
||||||
gdk_window_get_root_origin(GTK_WIDGET(mContainer)->window,
|
gdk_window_get_root_origin(GTK_WIDGET(mContainer)->window,
|
||||||
&x, &y);
|
&x, &y);
|
||||||
LOG(("WidgetToScreen (container) %d %d\n", x, y));
|
LOG(("WidgetToScreenOffset (container) %d %d\n", x, y));
|
||||||
}
|
}
|
||||||
else if (mDrawingarea) {
|
else if (mDrawingarea) {
|
||||||
gdk_window_get_origin(mDrawingarea->inner_window, &x, &y);
|
gdk_window_get_origin(mDrawingarea->inner_window, &x, &y);
|
||||||
LOG(("WidgetToScreen (drawing) %d %d\n", x, y));
|
LOG(("WidgetToScreenOffset (drawing) %d %d\n", x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
aNewRect.x = x + aOldRect.x;
|
return nsIntPoint(x, y);
|
||||||
aNewRect.y = y + aOldRect.y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsWindow::ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
|
||||||
{
|
|
||||||
gint x = 0, y = 0;
|
|
||||||
|
|
||||||
if (mContainer) {
|
|
||||||
gdk_window_get_root_origin(GTK_WIDGET(mContainer)->window,
|
|
||||||
&x, &y);
|
|
||||||
}
|
|
||||||
else if (mDrawingarea) {
|
|
||||||
gdk_window_get_origin(mDrawingarea->inner_window, &x, &y);
|
|
||||||
}
|
|
||||||
|
|
||||||
aNewRect.x = aOldRect.x - x;
|
|
||||||
aNewRect.y = aOldRect.y - y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -2390,10 +2363,7 @@ nsWindow::OnConfigureEvent(GtkWidget *aWidget, GdkEventConfigure *aEvent)
|
||||||
if (mIsTopLevel) {
|
if (mIsTopLevel) {
|
||||||
mPlaced = PR_TRUE;
|
mPlaced = PR_TRUE;
|
||||||
// Need to translate this into the right coordinates
|
// Need to translate this into the right coordinates
|
||||||
nsIntRect oldrect, newrect;
|
mBounds.MoveTo(WidgetToScreenOffset());
|
||||||
WidgetToScreen(oldrect, newrect);
|
|
||||||
mBounds.x = newrect.x;
|
|
||||||
mBounds.y = newrect.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsGUIEvent event(PR_TRUE, NS_MOVE, this);
|
nsGUIEvent event(PR_TRUE, NS_MOVE, this);
|
||||||
|
@ -2553,11 +2523,7 @@ nsWindow::OnMotionNotifyEvent(GtkWidget *aWidget, GdkEventMotion *aEvent)
|
||||||
mLastMotionPressure = pressure;
|
mLastMotionPressure = pressure;
|
||||||
event.pressure = mLastMotionPressure;
|
event.pressure = mLastMotionPressure;
|
||||||
|
|
||||||
nsRect windowRect;
|
event.refPoint = nsIntPoint(cursorX, cursorY) - WidgetToScreenOffset();
|
||||||
ScreenToWidget(nsRect(nscoord(cursorX), nscoord(cursorY), 1, 1), windowRect);
|
|
||||||
|
|
||||||
event.refPoint.x = windowRect.x;
|
|
||||||
event.refPoint.y = windowRect.y;
|
|
||||||
|
|
||||||
event.isShift = (aEvent->state & GDK_SHIFT_MASK)
|
event.isShift = (aEvent->state & GDK_SHIFT_MASK)
|
||||||
? PR_TRUE : PR_FALSE;
|
? PR_TRUE : PR_FALSE;
|
||||||
|
@ -2647,11 +2613,8 @@ nsWindow::OnMotionNotifyEvent(GtkWidget *aWidget, GdkEventMotion *aEvent)
|
||||||
event.refPoint.x = nscoord(aEvent->x);
|
event.refPoint.x = nscoord(aEvent->x);
|
||||||
event.refPoint.y = nscoord(aEvent->y);
|
event.refPoint.y = nscoord(aEvent->y);
|
||||||
} else {
|
} else {
|
||||||
nsIntRect windowRect;
|
nsIntPoint point(NSToIntFloor(aEvent->x_root), NSToIntFloor(aEvent->y_root));
|
||||||
ScreenToWidget(nsIntRect(NSToIntFloor(aEvent->x_root), NSToIntFloor(aEvent->y_root), 1, 1), windowRect);
|
event.refPoint = point - WidgetToScreenOffset();
|
||||||
|
|
||||||
event.refPoint.x = windowRect.x;
|
|
||||||
event.refPoint.y = windowRect.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event.isShift = (aEvent->state & GDK_SHIFT_MASK)
|
event.isShift = (aEvent->state & GDK_SHIFT_MASK)
|
||||||
|
@ -2678,11 +2641,8 @@ nsWindow::InitButtonEvent(nsMouseEvent &aEvent,
|
||||||
aEvent.refPoint.x = nscoord(aGdkEvent->x);
|
aEvent.refPoint.x = nscoord(aGdkEvent->x);
|
||||||
aEvent.refPoint.y = nscoord(aGdkEvent->y);
|
aEvent.refPoint.y = nscoord(aGdkEvent->y);
|
||||||
} else {
|
} else {
|
||||||
nsIntRect windowRect;
|
nsIntPoint point(NSToIntFloor(aGdkEvent->x_root), NSToIntFloor(aGdkEvent->y_root));
|
||||||
ScreenToWidget(nsIntRect(NSToIntFloor(aGdkEvent->x_root), NSToIntFloor(aGdkEvent->y_root), 1, 1), windowRect);
|
aEvent.refPoint = point - WidgetToScreenOffset();
|
||||||
|
|
||||||
aEvent.refPoint.x = windowRect.x;
|
|
||||||
aEvent.refPoint.y = windowRect.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aEvent.isShift = (aGdkEvent->state & GDK_SHIFT_MASK) != 0;
|
aEvent.isShift = (aGdkEvent->state & GDK_SHIFT_MASK) != 0;
|
||||||
|
@ -3233,18 +3193,15 @@ nsWindow::OnScrollEvent(GtkWidget *aWidget, GdkEventScroll *aEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aEvent->window == mDrawingarea->inner_window) {
|
if (aEvent->window == mDrawingarea->inner_window) {
|
||||||
// we are the window that the event happened on so no need for expensive ScreenToWidget
|
// we are the window that the event happened on so no need for expensive WidgetToScreenOffset
|
||||||
event.refPoint.x = nscoord(aEvent->x);
|
event.refPoint.x = nscoord(aEvent->x);
|
||||||
event.refPoint.y = nscoord(aEvent->y);
|
event.refPoint.y = nscoord(aEvent->y);
|
||||||
} else {
|
} else {
|
||||||
// XXX we're never quite sure which GdkWindow the event came from due to our custom bubbling
|
// XXX we're never quite sure which GdkWindow the event came from due to our custom bubbling
|
||||||
// in scroll_event_cb(), so use ScreenToWidget to translate the screen root coordinates into
|
// in scroll_event_cb(), so use ScreenToWidget to translate the screen root coordinates into
|
||||||
// coordinates relative to this widget.
|
// coordinates relative to this widget.
|
||||||
nsIntRect windowRect;
|
nsIntPoint point(NSToIntFloor(aEvent->x_root), NSToIntFloor(aEvent->y_root));
|
||||||
ScreenToWidget(nsIntRect(NSToIntFloor(aEvent->x_root), NSToIntFloor(aEvent->y_root), 1, 1), windowRect);
|
event.refPoint = point - WidgetToScreenOffset();
|
||||||
|
|
||||||
event.refPoint.x = windowRect.x;
|
|
||||||
event.refPoint.y = windowRect.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event.isShift = (aEvent->state & GDK_SHIFT_MASK) != 0;
|
event.isShift = (aEvent->state & GDK_SHIFT_MASK) != 0;
|
||||||
|
|
|
@ -208,10 +208,7 @@ public:
|
||||||
NS_IMETHOD SetWindowClass(const nsAString& xulWinType);
|
NS_IMETHOD SetWindowClass(const nsAString& xulWinType);
|
||||||
NS_IMETHOD SetMenuBar(void * aMenuBar);
|
NS_IMETHOD SetMenuBar(void * aMenuBar);
|
||||||
NS_IMETHOD ShowMenuBar(PRBool aShow);
|
NS_IMETHOD ShowMenuBar(PRBool aShow);
|
||||||
NS_IMETHOD WidgetToScreen(const nsIntRect& aOldRect,
|
virtual nsIntPoint WidgetToScreenOffset();
|
||||||
nsIntRect& aNewRect);
|
|
||||||
NS_IMETHOD ScreenToWidget(const nsIntRect& aOldRect,
|
|
||||||
nsIntRect& aNewRect);
|
|
||||||
NS_IMETHOD BeginResizingChildren(void);
|
NS_IMETHOD BeginResizingChildren(void);
|
||||||
NS_IMETHOD EndResizingChildren(void);
|
NS_IMETHOD EndResizingChildren(void);
|
||||||
NS_IMETHOD EnableDragDrop(PRBool aEnable);
|
NS_IMETHOD EnableDragDrop(PRBool aEnable);
|
||||||
|
|
|
@ -367,33 +367,15 @@ NS_METHOD nsWindow::EndResizingChildren(void)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_METHOD nsWindow::WidgetToScreen(const nsIntRect &aOldRect, nsIntRect &aNewRect)
|
nsIntPoint nsWindow::WidgetToScreenOffset()
|
||||||
{
|
{
|
||||||
POINTL point = { aOldRect.x, aOldRect.y };
|
POINTL point = { 0, 0 };
|
||||||
NS2PM( point);
|
NS2PM( point);
|
||||||
|
|
||||||
WinMapWindowPoints( mWnd, HWND_DESKTOP, &point, 1);
|
WinMapWindowPoints( mWnd, HWND_DESKTOP, &point, 1);
|
||||||
|
|
||||||
aNewRect.x = point.x;
|
return nsIntPoint(point.x,
|
||||||
aNewRect.y = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN) - point.y - 1;
|
WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN) - point.y - 1);
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_METHOD nsWindow::ScreenToWidget( const nsIntRect &aOldRect, nsIntRect &aNewRect)
|
|
||||||
{
|
|
||||||
POINTL point = { aOldRect.x,
|
|
||||||
WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN) - aOldRect.y - 1 };
|
|
||||||
WinMapWindowPoints( HWND_DESKTOP, mWnd, &point, 1);
|
|
||||||
|
|
||||||
PM2NS( point);
|
|
||||||
|
|
||||||
aNewRect.x = point.x;
|
|
||||||
aNewRect.y = point.y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
|
@ -162,8 +162,7 @@ class nsWindow : public nsBaseWidget,
|
||||||
|
|
||||||
NS_IMETHOD BeginResizingChildren();
|
NS_IMETHOD BeginResizingChildren();
|
||||||
NS_IMETHOD EndResizingChildren();
|
NS_IMETHOD EndResizingChildren();
|
||||||
NS_IMETHOD WidgetToScreen( const nsIntRect &aOldRect, nsIntRect &aNewRect);
|
virtual nsIntPoint WidgetToScreenOffset();
|
||||||
NS_IMETHOD ScreenToWidget( const nsIntRect &aOldRect, nsIntRect &aNewRect);
|
|
||||||
NS_IMETHOD DispatchEvent( struct nsGUIEvent *event, nsEventStatus &aStatus);
|
NS_IMETHOD DispatchEvent( struct nsGUIEvent *event, nsEventStatus &aStatus);
|
||||||
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
|
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
|
||||||
|
|
||||||
|
|
|
@ -416,13 +416,8 @@ nsWindow::Move(PRInt32 aX, PRInt32 aY)
|
||||||
QPoint pos(aX, aY);
|
QPoint pos(aX, aY);
|
||||||
if (mDrawingArea) {
|
if (mDrawingArea) {
|
||||||
if (mParent && mDrawingArea->windowType() == Qt::Popup) {
|
if (mParent && mDrawingArea->windowType() == Qt::Popup) {
|
||||||
nsIntRect oldrect, newrect;
|
if (mParent->mDrawingArea)
|
||||||
oldrect.x = aX;
|
pos = mParent->mDrawingArea->mapToGlobal(pos);
|
||||||
oldrect.y = aY;
|
|
||||||
|
|
||||||
mParent->WidgetToScreen(oldrect, newrect);
|
|
||||||
|
|
||||||
pos = QPoint(newrect.x, newrect.y);
|
|
||||||
#ifdef DEBUG_WIDGETS
|
#ifdef DEBUG_WIDGETS
|
||||||
qDebug("pos is [%d,%d]", pos.x(), pos.y());
|
qDebug("pos is [%d,%d]", pos.x(), pos.y());
|
||||||
#endif
|
#endif
|
||||||
|
@ -588,8 +583,7 @@ nsWindow::SetFocus(PRBool aRaise)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsWindow::GetScreenBounds(nsIntRect &aRect)
|
nsWindow::GetScreenBounds(nsIntRect &aRect)
|
||||||
{
|
{
|
||||||
nsIntRect origin(0, 0, mBounds.width, mBounds.height);
|
aRect = nsIntRect(WidgetToScreenOffset(), mBounds.Size());
|
||||||
WidgetToScreen(origin, aRect);
|
|
||||||
LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
|
LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
|
||||||
aRect.x, aRect.y,
|
aRect.x, aRect.y,
|
||||||
mBounds.width, mBounds.height,
|
mBounds.width, mBounds.height,
|
||||||
|
@ -913,36 +907,15 @@ nsWindow::ShowMenuBar(PRBool aShow)
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
nsIntPoint
|
||||||
nsWindow::WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
nsWindow::WidgetToScreenOffset()
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mDrawingArea, NS_OK);
|
NS_ENSURE_TRUE(mDrawingArea, nsIntPoint(0,0));
|
||||||
|
|
||||||
QPoint origin(aOldRect.x, aOldRect.y);
|
QPoint origin(0, 0);
|
||||||
origin = mDrawingArea->mapToGlobal(origin);
|
origin = mDrawingArea->mapToGlobal(origin);
|
||||||
|
|
||||||
aNewRect.x = origin.x();
|
return nsIntPoint(origin.x(), origin.y());
|
||||||
aNewRect.y = origin.y();
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsWindow::ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
|
||||||
{
|
|
||||||
NS_ENSURE_TRUE(mDrawingArea, NS_OK);
|
|
||||||
|
|
||||||
QPoint origin(aOldRect.x, aOldRect.y);
|
|
||||||
origin = mDrawingArea->mapFromGlobal(origin);
|
|
||||||
|
|
||||||
aNewRect.x = origin.x();
|
|
||||||
aNewRect.y = origin.y();
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -1225,10 +1198,7 @@ nsWindow::OnMoveEvent(QMoveEvent *aEvent)
|
||||||
QPoint pos = aEvent->pos();
|
QPoint pos = aEvent->pos();
|
||||||
if (mIsTopLevel) {
|
if (mIsTopLevel) {
|
||||||
// Need to translate this into the right coordinates
|
// Need to translate this into the right coordinates
|
||||||
nsIntRect oldrect, newrect;
|
mBounds.MoveTo(WidgetToScreenOffset());
|
||||||
WidgetToScreen(oldrect, newrect);
|
|
||||||
mBounds.x = newrect.x;
|
|
||||||
mBounds.y = newrect.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsGUIEvent event(PR_TRUE, NS_MOVE, this);
|
nsGUIEvent event(PR_TRUE, NS_MOVE, this);
|
||||||
|
@ -1905,13 +1875,8 @@ nsWindow::NativeResize(PRInt32 aX, PRInt32 aY,
|
||||||
if (mDrawingArea)
|
if (mDrawingArea)
|
||||||
{
|
{
|
||||||
if (mParent && mDrawingArea->windowType() == Qt::Popup) {
|
if (mParent && mDrawingArea->windowType() == Qt::Popup) {
|
||||||
nsIntRect oldrect, newrect;
|
if (mParent->mDrawingArea)
|
||||||
oldrect.x = aX;
|
pos = mParent->mDrawingArea->mapToGlobal(pos);
|
||||||
oldrect.y = aY;
|
|
||||||
|
|
||||||
mParent->WidgetToScreen(oldrect, newrect);
|
|
||||||
|
|
||||||
pos = QPoint(newrect.x, newrect.y);
|
|
||||||
#ifdef DEBUG_WIDGETS
|
#ifdef DEBUG_WIDGETS
|
||||||
qDebug("pos is [%d,%d]", pos.x(), pos.y());
|
qDebug("pos is [%d,%d]", pos.x(), pos.y());
|
||||||
#endif
|
#endif
|
||||||
|
@ -2537,13 +2502,8 @@ nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
|
||||||
// XXXvlad what?
|
// XXXvlad what?
|
||||||
#if 0
|
#if 0
|
||||||
if (mParent && mDrawingArea->windowType() == Qt::Popup) {
|
if (mParent && mDrawingArea->windowType() == Qt::Popup) {
|
||||||
nsIntRect oldrect, newrect;
|
if (mParent->mDrawingArea)
|
||||||
oldrect.x = aX;
|
pos = mParent->mDrawingArea->mapToGlobal(pos);
|
||||||
oldrect.y = aY;
|
|
||||||
|
|
||||||
mParent->WidgetToScreen(oldrect, newrect);
|
|
||||||
|
|
||||||
pos = QPoint(newrect.x, newrect.y);
|
|
||||||
#ifdef DEBUG_WIDGETS
|
#ifdef DEBUG_WIDGETS
|
||||||
qDebug("pos is [%d,%d]", pos.x(), pos.y());
|
qDebug("pos is [%d,%d]", pos.x(), pos.y());
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -196,10 +196,7 @@ public:
|
||||||
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
|
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
|
||||||
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
|
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
|
||||||
NS_IMETHOD ShowMenuBar(PRBool aShow);
|
NS_IMETHOD ShowMenuBar(PRBool aShow);
|
||||||
NS_IMETHOD WidgetToScreen(const nsIntRect& aOldRect,
|
virtual nsIntPoint WidgetToScreenOffset();
|
||||||
nsIntRect& aNewRect);
|
|
||||||
NS_IMETHOD ScreenToWidget(const nsIntRect& aOldRect,
|
|
||||||
nsIntRect& aNewRect);
|
|
||||||
NS_IMETHOD BeginResizingChildren(void);
|
NS_IMETHOD BeginResizingChildren(void);
|
||||||
NS_IMETHOD EndResizingChildren(void);
|
NS_IMETHOD EndResizingChildren(void);
|
||||||
NS_IMETHOD GetPreferredSize (PRInt32 &aWidth,
|
NS_IMETHOD GetPreferredSize (PRInt32 &aWidth,
|
||||||
|
|
|
@ -642,9 +642,7 @@ nsTextStore::GetTextExt(TsViewCookie vcView,
|
||||||
refWindow = refWindow->GetTopLevelWindow(PR_FALSE);
|
refWindow = refWindow->GetTopLevelWindow(PR_FALSE);
|
||||||
NS_ENSURE_TRUE(refWindow, E_FAIL);
|
NS_ENSURE_TRUE(refWindow, E_FAIL);
|
||||||
|
|
||||||
nsresult rv = refWindow->WidgetToScreen(event.mReply.mRect,
|
event.mReply.mRect.MoveBy(refWindow->WidgetToScreenOffset());
|
||||||
event.mReply.mRect);
|
|
||||||
NS_ENSURE_SUCCESS(rv, E_FAIL);
|
|
||||||
|
|
||||||
// get bounding screen rect to test for clipping
|
// get bounding screen rect to test for clipping
|
||||||
HRESULT hr = GetScreenExt(vcView, prc);
|
HRESULT hr = GetScreenExt(vcView, prc);
|
||||||
|
@ -686,10 +684,8 @@ nsTextStore::GetScreenExt(TsViewCookie vcView,
|
||||||
|
|
||||||
// Clip frame rect to window rect
|
// Clip frame rect to window rect
|
||||||
boundRect.IntersectRect(event.mReply.mRect, boundRect);
|
boundRect.IntersectRect(event.mReply.mRect, boundRect);
|
||||||
rv = refWindow->WidgetToScreen(boundRect, boundRect);
|
|
||||||
NS_ENSURE_SUCCESS(rv, E_FAIL);
|
|
||||||
|
|
||||||
if (!boundRect.IsEmpty()) {
|
if (!boundRect.IsEmpty()) {
|
||||||
|
boundRect.MoveBy(refWindow->WidgetToScreenOffset());
|
||||||
::SetRect(prc, boundRect.x, boundRect.y,
|
::SetRect(prc, boundRect.x, boundRect.y,
|
||||||
boundRect.XMost(), boundRect.YMost());
|
boundRect.XMost(), boundRect.YMost());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -903,30 +903,13 @@ NS_METHOD nsWindow::EndResizingChildren(void)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_METHOD nsWindow::WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
nsIntPoint nsWindow::WidgetToScreenOffset()
|
||||||
{
|
{
|
||||||
POINT point;
|
POINT point;
|
||||||
point.x = aOldRect.x;
|
point.x = 0;
|
||||||
point.y = aOldRect.y;
|
point.y = 0;
|
||||||
::ClientToScreen(mWnd, &point);
|
::ClientToScreen(mWnd, &point);
|
||||||
aNewRect.x = point.x;
|
return nsIntPoint(point.x, point.y);
|
||||||
aNewRect.y = point.y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_METHOD nsWindow::ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect)
|
|
||||||
{
|
|
||||||
POINT point;
|
|
||||||
point.x = aOldRect.x;
|
|
||||||
point.y = aOldRect.y;
|
|
||||||
::ScreenToClient(mWnd, &point);
|
|
||||||
aNewRect.x = point.x;
|
|
||||||
aNewRect.y = point.y;
|
|
||||||
aNewRect.width = aOldRect.width;
|
|
||||||
aNewRect.height = aOldRect.height;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LPARAM nsWindow::lParamToScreen(LPARAM lParam)
|
LPARAM nsWindow::lParamToScreen(LPARAM lParam)
|
||||||
|
@ -6307,11 +6290,7 @@ PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
|
||||||
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
event.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
||||||
event.button = aButton;
|
event.button = aButton;
|
||||||
|
|
||||||
nsIntRect mpWidget;
|
nsIntPoint mpScreen = eventPoint + WidgetToScreenOffset();
|
||||||
nsIntRect mpScreen;
|
|
||||||
mpWidget.x = eventPoint.x;
|
|
||||||
mpWidget.y = eventPoint.y;
|
|
||||||
WidgetToScreen(mpWidget, mpScreen);
|
|
||||||
|
|
||||||
// Suppress mouse moves caused by widget creation
|
// Suppress mouse moves caused by widget creation
|
||||||
if (aEventType == NS_MOUSE_MOVE)
|
if (aEventType == NS_MOUSE_MOVE)
|
||||||
|
@ -7573,10 +7552,10 @@ nsWindow::ResolveIMECaretPos(nsIWidget* aReferenceWidget,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (aReferenceWidget)
|
if (aReferenceWidget)
|
||||||
aReferenceWidget->WidgetToScreen(aOutRect, aOutRect);
|
aOutRect.MoveBy(aReferenceWidget->WidgetToScreenOffset());
|
||||||
|
|
||||||
if (aNewOriginWidget)
|
if (aNewOriginWidget)
|
||||||
aNewOriginWidget->ScreenToWidget(aOutRect, aOutRect);
|
aOutRect.MoveBy(-aNewOriginWidget->WidgetToScreenOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -196,8 +196,7 @@ public:
|
||||||
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
|
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
|
||||||
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
|
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
|
||||||
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
|
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
|
||||||
NS_IMETHOD WidgetToScreen(const nsIntRect& aOldRect, nsIntRect& aNewRect);
|
virtual nsIntPoint WidgetToScreenOffset();
|
||||||
NS_IMETHOD ScreenToWidget(const nsIntRect& aOldRect, nsIntRect& aNewRect);
|
|
||||||
NS_IMETHOD BeginResizingChildren(void);
|
NS_IMETHOD BeginResizingChildren(void);
|
||||||
NS_IMETHOD EndResizingChildren(void);
|
NS_IMETHOD EndResizingChildren(void);
|
||||||
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight);
|
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче