Bug 228282 - [Accessibility] Table & Tree with no column headers say "sort button" on Leopard
Summary: [Accessibility] Table & Tree with no column headers say "sort button" on Leopard
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.3   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 normal (vote)
Target Milestone: 3.4 RC2   Edit
Assignee: Carolyn MacLeod CLA
QA Contact:
URL:
Whiteboard:
Keywords: accessibility
Depends on:
Blocks:
 
Reported: 2008-04-22 16:54 EDT by Carolyn MacLeod CLA
Modified: 2008-05-20 15:33 EDT (History)
5 users (show)

See Also:
Silenio_Quarti: review+
duongn: review+


Attachments
_patch.txt (7.45 KB, patch)
2008-05-18 15:53 EDT, Carolyn MacLeod CLA
no flags Details | Diff
_patch.txt (2.22 KB, patch)
2008-05-18 16:26 EDT, Carolyn MacLeod CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Carolyn MacLeod CLA 2008-04-22 16:54:39 EDT
Run ControlExample and go to Table tab.
Start VoiceOver (command+F5).
Tab into the Table, and type down arrow to select the first row.
VoiceOver says "sort button" before saying the contents of every cell.
This would be pretty annoying and confusing to a VoiceOver user.

To see what is happening, select "Column Headers". Now, the column headers each have a name.
Type down arrow to select the next row.
Now, VoiceOver says each table header before it says the cell contents, and it sounds correct.
So the problem must be that the column headers exist - with no text - even when the columns are not visible, and VoiceOver says their description (sort button) because they have no name.

Hide the column headers by deselecting "Column Headers" and type down arrow one more time.
Now, the column header names that were visible are being spoken, instead of "sort button".

Verified that this is a problem even in a minimal snippet.

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;

public class TableTest {
	
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new GridLayout());
		shell.setText("Table");
		
		Table table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
		table.setLayoutData(new GridData(GridData.FILL_BOTH));
//		table.setHeaderVisible(true);
		for (int col = 0; col < 3; col++) {
			TableColumn column = new TableColumn(table, SWT.NONE);
//			column.setText("Column " + col);
			column.setWidth(100);
		}
		for (int row = 0; row < 5; row++) {
			TableItem item = new TableItem(table, SWT.NONE);
			for (int col = 0; col < 3; col++) {
				item.setText(col, "item" + col + row);
			}
		}

		shell.pack();
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) display.sleep();
		}
	}
}
Comment 1 Carolyn MacLeod CLA 2008-05-16 13:38:02 EDT
I can get VoiceOver to stop saying "sort button" for invisible header buttons by using this extreme hack:

- when the column headers are not visible:
     - set the title of the header buttons to space (must be space - empty string doesn't help)
     - set the height of the header buttons to 1 pixel instead of 0

This tells VoiceOver that there are some "visible" (by 1 pixel) column header buttons, and they do have a title, but there's no need to read it. So VoiceOver works exactly the way I would expect it to for invisible column headers - it simply reads the text for each item in the selected row.

Since I am quite sure this very bad hack would cause a bunch of other problems, I'm still looking for a solution...

In case it's useful, here is a reference to the Apple radar that was fixed - and now causes this problem for invisible header buttons:

"DataBrowser's list view header buttons now report the kAXSortButton subrole (3502758)."
Comment 2 Carolyn MacLeod CLA 2008-05-18 15:53:26 EDT
Created attachment 100836 [details]
_patch.txt

This fixes the bug by telling VoiceOver that there is no header when the header is not visible.
Comment 3 Carolyn MacLeod CLA 2008-05-18 15:55:36 EDT
SSQ and Duong, please drop by for a demo, and to review fix for RC2.

The attached patch is only for Table, but the identical change fixes Tree also.
Comment 4 Carolyn MacLeod CLA 2008-05-18 16:26:58 EDT
Created attachment 100839 [details]
_patch.txt

Here is a similar patch that is also needed for List.
Comment 5 Steve Northover CLA 2008-05-19 15:47:26 EDT
Sounds bad.  Can't we get in the way and stop reporting "kAXSortButton subrole"?
Comment 6 Carolyn MacLeod CLA 2008-05-20 01:42:46 EDT
It didn't feel bad - I just return nothing when asked for the AXHeaderAttribute and the header isn't visible.

I tried returning empty string when the AXRoleDescriptionAttribute was "sort button", but to do it properly (i.e. so it would be NLS safe) required more code and I couldn't quite get that to work.

I'm not sure what would happen if I return nothing for AXSubroleAttribute when the outline would normally be returning AXSortButtonSubrole, but that feels "more bad" than just saying there's no header when there's no header.
The role would have been already been reported (I believe the sort buttons are "AXOutlineRole:AXSortButtonSubrole" or "AXHeaderRole:AXSortButtonSubrole") and if I don't answer a subrole, then I think VO is going to assume it's looking at something else.
Comment 7 Carolyn MacLeod CLA 2008-05-20 01:57:04 EDT
What I am saying is that I think the current fix is quite nice, and it feels natural, and it feels safe. The patch looks more complicated than it really is because some code had to be moved up to be reused and some other code ended up inside an else.

The 'meat' of the change is here (more comment lines than actual code <g>):

if (attributeName.equals(OS.kAXHeaderAttribute)) {
	/*
	* Bug in the Macintosh.  Even when the header is not visible,
	* VoiceOver still reports each column header's role for every row.
	* This is confusing and overly verbose.  The fix is to return
	* "no header" when the screen reader asks for the header, by
	* returning noErr without setting the event parameter.
	*/
	code = OS.noErr;
}
Comment 8 Carolyn MacLeod CLA 2008-05-20 02:03:25 EDT
Oops - that was the change for List (Hmm... I think the comment needs tweaking).

The change for Table & Tree also does the getHeaderVisible() check (inline):

if (attributeName.equals(OS.kAXHeaderAttribute)) {
	short [] height = new short [1];
	OS.GetDataBrowserListViewHeaderBtnHeight (handle, height);
	if (height [0] == 0) {
		/*
		* Bug in the Macintosh.  Even when the header is not visible,
		* VoiceOver still reports each column header's role for every row.
		* This is confusing and overly verbose.  The fix is to return
		* "no header" when the screen reader asks for the header, by
		* returning noErr without setting the event parameter.
		*/
		code = OS.noErr;
	}

}
Comment 9 Steve Northover CLA 2008-05-20 12:36:40 EDT
I read the words "extreme hack" and something about sizing to "one pixel" height and got scared.
Comment 10 Carolyn MacLeod CLA 2008-05-20 13:15:00 EDT
Ah, I see. I didn't use the "solution" that I mentioned in comment 1 - for that very reason. That one didn't feel right at all <g>.

The patches in comment 2 and comment 4 are completely unrelated to the notes in comment 1. Sorry for the confusion.
Comment 11 Carolyn MacLeod CLA 2008-05-20 15:33:23 EDT
Fixed > 20080520 and the fix will be in 3.4 RC2.