Bug 1680840: Fire table styling changed event when style changes that may affect data/layout table classification r=emilio,eeejay

Differential Revision: https://phabricator.services.mozilla.com/D103254
This commit is contained in:
Morgan Reschenberg 2021-02-04 20:50:05 +00:00
parent 90780fa3c1
commit 1f72fbb6eb
10 changed files with 134 additions and 2 deletions

View File

@ -498,6 +498,16 @@ void nsAccessibilityService::ContentRemoved(PresShell* aPresShell,
#endif #endif
} }
void nsAccessibilityService::TableLayoutGuessMaybeChanged(
PresShell* aPresShell, nsIContent* aContent) {
if (DocAccessible* document = GetDocAccessible(aPresShell)) {
if (Accessible* accessible = document->GetAccessible(aContent)) {
document->FireDelayedEvent(
nsIAccessibleEvent::EVENT_TABLE_STYLING_CHANGED, accessible);
}
}
}
void nsAccessibilityService::UpdateText(PresShell* aPresShell, void nsAccessibilityService::UpdateText(PresShell* aPresShell,
nsIContent* aContent) { nsIContent* aContent) {
DocAccessible* document = GetDocAccessible(aPresShell); DocAccessible* document = GetDocAccessible(aPresShell);

View File

@ -173,6 +173,12 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
*/ */
void ContentRemoved(mozilla::PresShell* aPresShell, nsIContent* aChild); void ContentRemoved(mozilla::PresShell* aPresShell, nsIContent* aChild);
/**
* Notification used to invalidate the isLayoutTable cache.
*/
void TableLayoutGuessMaybeChanged(mozilla::PresShell* aPresShell,
nsIContent* aContent);
void UpdateText(mozilla::PresShell* aPresShell, nsIContent* aContent); void UpdateText(mozilla::PresShell* aPresShell, nsIContent* aContent);
/** /**
@ -498,6 +504,7 @@ static const char kEventTypeNames[][40] = {
"announcement", // EVENT_ANNOUNCEMENT "announcement", // EVENT_ANNOUNCEMENT
"live region added", // EVENT_LIVE_REGION_ADDED "live region added", // EVENT_LIVE_REGION_ADDED
"live region removed", // EVENT_LIVE_REGION_REMOVED "live region removed", // EVENT_LIVE_REGION_REMOVED
"table styling changed", // EVENT_TABLE_STYLING_CHANGED
}; };
#endif #endif

View File

@ -1551,6 +1551,13 @@ bool DocAccessible::PruneOrInsertSubtree(nsIContent* aRoot) {
SelectionMgr()->SetControlSelectionListener(aRoot->AsElement()); SelectionMgr()->SetControlSelectionListener(aRoot->AsElement());
} }
// If the accessible is a table, or table part, its layout table
// status may have changed. We need to invalidate the associated
// cache, which listens for the following event.
if (acc->IsTable() || acc->IsTableRow() || acc->IsTableCell()) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_TABLE_STYLING_CHANGED, acc);
}
// The accessible can be reparented or reordered in its parent. // The accessible can be reparented or reordered in its parent.
// We schedule it for reinsertion. For example, a slotted element // We schedule it for reinsertion. For example, a slotted element
// can change its slot attribute to a different slot. // can change its slot attribute to a different slot.

View File

@ -438,10 +438,16 @@ interface nsIAccessibleEvent : nsISupports
*/ */
const unsigned long EVENT_LIVE_REGION_REMOVED = 0x005B; const unsigned long EVENT_LIVE_REGION_REMOVED = 0x005B;
/**
* A style change has occured on a table that may cause it to
* change from data to layout table, or the reverse.
*/
const unsigned long EVENT_TABLE_STYLING_CHANGED = 0x005C;
/** /**
* Help make sure event map does not get out-of-line. * Help make sure event map does not get out-of-line.
*/ */
const unsigned long EVENT_LAST_ENTRY = 0x005C; const unsigned long EVENT_LAST_ENTRY = 0x005D;
/** /**
* The type of event, based on the enumerated event values * The type of event, based on the enumerated event values

View File

@ -55,6 +55,7 @@ skip-if = os == 'mac'
[test_selection_aria.html] [test_selection_aria.html]
[test_statechange.html] [test_statechange.html]
[test_statechange_tabpanels.xhtml] [test_statechange_tabpanels.xhtml]
[test_stylechange.html]
[test_text.html] [test_text.html]
[test_text_alg.html] [test_text_alg.html]
[test_textattrchange.html] [test_textattrchange.html]

View File

@ -0,0 +1,59 @@
<!doctype html>
<head>
<title>Table accessible style change event testing</title>
<link rel="stylesheet"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="../common.js"></script>
<script src="../promisified-events.js"></script>
<script type="application/javascript">
async function testGotStyleChange(elem, name, value) {
let waitFor = waitForEvent(
EVENT_TABLE_STYLING_CHANGED, elem
);
if (value) {
document.getElementById(elem).style.setProperty(name, value);
} else {
document.getElementById(elem).style.removeProperty(name);
}
await waitFor;
}
async function doTests() {
info("Set new row background");
await testGotStyleChange("rowOne", "background-color", "green");
info("Remove row background");
await testGotStyleChange("rowOne", "background-color", null);
info("Change cell border");
await testGotStyleChange("cellOne", "border", "5px solid green");
info("Remove cell border");
await testGotStyleChange("cellOne", "border", null);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<table>
<tr id="rowOne" style="background-color: red;">
<td id="cellOne">cell1</td>
<td>cell2</td>
</tr>
<tr>
<td>cell3</td>
<td>cell4</td>
</tr>
</table>
</body>
</html>

View File

@ -15,7 +15,7 @@
EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE, EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE,
EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS, EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS,
EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED, EVENT_ALERT, EVENT_DOCUMENT_RELOAD, EVENT_VIRTUALCURSOR_CHANGED, EVENT_ALERT,
EVENT_OBJECT_ATTRIBUTE_CHANGED, UnexpectedEvents, waitForEvent, EVENT_OBJECT_ATTRIBUTE_CHANGED, EVENT_TABLE_STYLING_CHANGED, UnexpectedEvents, waitForEvent,
waitForEvents, waitForOrderedEvents */ waitForEvents, waitForOrderedEvents */
const EVENT_ANNOUNCEMENT = nsIAccessibleEvent.EVENT_ANNOUNCEMENT; const EVENT_ANNOUNCEMENT = nsIAccessibleEvent.EVENT_ANNOUNCEMENT;
@ -47,6 +47,8 @@ const EVENT_LIVE_REGION_ADDED = nsIAccessibleEvent.EVENT_LIVE_REGION_ADDED;
const EVENT_LIVE_REGION_REMOVED = nsIAccessibleEvent.EVENT_LIVE_REGION_REMOVED; const EVENT_LIVE_REGION_REMOVED = nsIAccessibleEvent.EVENT_LIVE_REGION_REMOVED;
const EVENT_OBJECT_ATTRIBUTE_CHANGED = const EVENT_OBJECT_ATTRIBUTE_CHANGED =
nsIAccessibleEvent.EVENT_OBJECT_ATTRIBUTE_CHANGED; nsIAccessibleEvent.EVENT_OBJECT_ATTRIBUTE_CHANGED;
const EVENT_TABLE_STYLING_CHANGED =
nsIAccessibleEvent.EVENT_TABLE_STYLING_CHANGED;
const EventsLogger = { const EventsLogger = {
enabled: false, enabled: false,

View File

@ -104,5 +104,6 @@ static const uint32_t gWinEventMap[] = {
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_ANNOUNCEMENT kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_ANNOUNCEMENT
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED
kEVENT_WIN_UNKNOWN, // nsIAccessibleEvent::EVENT_TABLE_STYLING_CHANGED
// clang-format on // clang-format on
}; };

View File

@ -35,6 +35,10 @@
#include "nsFrameSelection.h" #include "nsFrameSelection.h"
#include "mozilla/LookAndFeel.h" #include "mozilla/LookAndFeel.h"
#ifdef ACCESSIBILITY
# include "nsAccessibilityService.h"
#endif
using namespace mozilla; using namespace mozilla;
using namespace mozilla::gfx; using namespace mozilla::gfx;
using namespace mozilla::image; using namespace mozilla::image;
@ -213,6 +217,19 @@ void nsTableCellFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
if (!aOldComputedStyle) // avoid this on init if (!aOldComputedStyle) // avoid this on init
return; return;
#ifdef ACCESSIBILITY
if (nsAccessibilityService* accService = GetAccService()) {
if (StyleBorder()->GetComputedBorder() !=
aOldComputedStyle->StyleBorder()->GetComputedBorder()) {
// If a table cell's computed border changes, it can change whether or
// not its parent table is classified as a layout or data table. We
// send a notification here to invalidate the a11y cache on the table
// so the next fetch of IsProbablyLayoutTable() is accurate.
accService->TableLayoutGuessMaybeChanged(PresShell(), mContent);
}
}
#endif
nsTableFrame* tableFrame = GetTableFrame(); nsTableFrame* tableFrame = GetTableFrame();
if (tableFrame->IsBorderCollapse() && if (tableFrame->IsBorderCollapse() &&
tableFrame->BCRecalcNeeded(aOldComputedStyle, Style())) { tableFrame->BCRecalcNeeded(aOldComputedStyle, Style())) {

View File

@ -26,6 +26,10 @@
#include "nsIFrameInlines.h" #include "nsIFrameInlines.h"
#include <algorithm> #include <algorithm>
#ifdef ACCESSIBILITY
# include "nsAccessibilityService.h"
#endif
using namespace mozilla; using namespace mozilla;
namespace mozilla { namespace mozilla {
@ -174,6 +178,24 @@ void nsTableRowFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
if (!aOldComputedStyle) // avoid this on init if (!aOldComputedStyle) // avoid this on init
return; return;
#ifdef ACCESSIBILITY
if (nsAccessibilityService* accService = GetAccService()) {
// If a table row's background color is now different from
// the background color of its previous row, it is possible our
// table now has alternating row colors. This changes whether or not
// the table is classified as a layout table or data table.
// We invalidate on every background color change to avoid
// walking the tree in search of the nearest row.
if (StyleBackground()->BackgroundColor(this) !=
aOldComputedStyle->StyleBackground()->BackgroundColor(
aOldComputedStyle)) {
// We send a notification here to invalidate the a11y cache on the
// table so the next fetch of IsProbablyLayoutTable() is accurate.
accService->TableLayoutGuessMaybeChanged(PresShell(), mContent);
}
}
#endif
nsTableFrame* tableFrame = GetTableFrame(); nsTableFrame* tableFrame = GetTableFrame();
if (tableFrame->IsBorderCollapse() && if (tableFrame->IsBorderCollapse() &&
tableFrame->BCRecalcNeeded(aOldComputedStyle, Style())) { tableFrame->BCRecalcNeeded(aOldComputedStyle, Style())) {