Community
Participate
Working Groups
At no point when you are tabbing around do you get told what view you are in by JAWS
We may have to resort to a script to detect this case. The view activation is custom SWT code.
Platform limitation. Can be deferred.
Marking as later as it is a platfomr limitation.
Should investigate what the new accessibility API will allow.
Agree, this would be valuable. Perhaps changing the pane to return the view's tab name or title as the accessible name. The title would be better since it often has more info (e.g. the tasks and search views).
This is another case where JAWS will ask for the name of the widget via the accessibility interface and then do nothing with it. Adding Bug 21771 as a blocking bug.
This is the type of information that the user would normally expect JAWS to report with insert+tab or insert+t. Making it do that would require two things: that the information be available to JAWS script functions via the Eclipse window hierarchy and writing a JAWS script to support it. I'm willing to write the script. However, there are several ways this information could be made available to the user without any scripting. The best idea I have is to provide functions that will put up a view list and a perspective list. It sort of already exists. I noticed that if one presses ctrl+f7 followed by ctrl+shift+f7 without releasing the ctrl key then a list of views takes focus. This is really cool and useful but very backdoor. If I could just press something like alt+f7 to pop up the list then I could find out the current view with JAWS because its title would have focus. Actually, if one was to be more "consistent" with Windows-like conventions, a better list of key assignments would be: ctrl+f7 = view list alt+f7 = next view alt+shift+f7 = previous view ... similar for perspectives and editors. This is analogous to the Windows alt+tab and alt+shift+tab. Windows is missing an assignment to control+tab. We had one in OS/2 ... control+escape pulled up a list of open windows.
Needs to be retested in "New Look" views.
Assigning to me for retest
Now the view titles are tabs but JAWS does not read them. Window Eyes does as does MSAA. Moving back to SWT for investigation.
See bug 48846 for more details
Try reclassing the control as MSAA in JAWS. 1. Put focus on a tab 2. press insert+7 3. Choose MS Active accessibility from the list 4. Press add class and OK Now see if it works. If not, you can undo the change. If it does work, then Frank could take up issue of requiring the reclassification with FS. The goal is to avoid requiring all kinds of that type of customization to JAWS.
Note that the problem here may be due to the parenting relationships used in the Workbench. View panes are parented under the main content area of the window, not the CTabFolder. They're just positioned under the CTabFolder. This allows us to use the same ViewPanes without reparenting when switching between perspectives, fast views, etc. Should compare with a standalone SWT example.
This comment is similar to comment #7, but maybe a bit more info. I just added this comment to bug 37276, and then decided to paste it here also. Bug 37276 may be a dup, but I will let the UI team decide that. ----- FYI, this is a bit of a hack, but one way to have JAWS and Window-Eyes read the current View name or the current Editor name is to use the eclipse CTRL+F6/F7 hotkeys. These allow navigating to editors/views in a similar manner to the way Windows' & GTK's ALT+TAB and ALT+SHIFT+TAB let you cycle through (and navigate to) application windows. Here are the eclipse hotkeys in detail: CTRL+F6 - open a list of editors, with the 'next' one selected. Release the keys to navigate to the selected editor. Type CTRL+F6, and release, twice in a row to get the screen reader to read the name of the current editor. CTRL+SHIFT+F6 - open a list of editors, with the 'previous' one selected. Release the keys to navigate to the selected editor. Type CTRL+SHIFT+F6, and release, twice in a row to get the screen reader to read the name of the current editor. CTRL+F7 - open a list of views, with the 'next' one selected. Release the keys to navigate to the selected view. Type CTRL+F7, and release, twice in a row to get the screen reader to read the name of the current view. CTRL+SHIFT+F7 - open a list of views, with the 'previous' one selected. Release the keys to navigate to the selected view. Type CTRL+SHIFT+F7, and release, twice in a row to get the screen reader to read the name of the current view.
To address Nick's comment 13, I have a standalone SWT CTabFolder example. When comparing eclipse view and editor CTabFolders with SWT standalone CTabFolders, you will note that there are quite a few differences in keyboard access and screen reader accessibility capabilities. 1) User can change the pages of a standalone CTabFolder using ctrl+PgUp and ctrl+PgDown. I don't know who in eclipse is eating ctrl+PgUp and ctrl+PgDown, but it is not getting to the view or editor CTabFolders. 2) User can always use ctrl+Tab or shift+Tab to give focus to a standalone CTabFolder's tab label, and from there, user can always use left/right arrow keys to flip through the tabs. In eclipse views and editors, you can only sometimes use ctrl+Tab or shift+Tab to give focus to the tabs (for example, the editors always eat them), and even then, the left/right arrow keys are almost always eaten (they seem to be eaten by the child of the tab?). So sometimes, but not always, the user can type shift+Tab, arrow, shift+Tab, arrow, etc to cycle through the tabs. But in the standalone, there is no eating of any keys at all, so all are available for traversal. 3) Because of the ease of switching focus to the tab label of a standalone CTabFolder, JAWS has no trouble reading CTabFolder tab labels in the standalone example. The user can at any time switch focus to any tab label, which will then be read. It can then be reread with INS+Tab, or if the shell loses and regains focus, the tab label is reread. As switching focus to a tab label in eclipse is not reliable, it is not the recommended way to get JAWS or any screen reader to read the tab labels. Does the UI team have any time to investigate who is eating all of these traversal keys (and why) in eclipse?
*** Bug 37276 has been marked as a duplicate of this bug. ***
There are three reasons for the problems above. 1. Views and editors are not children of the tab folder, so Ctrl+Page_Up etc are not propogated by the OS to the folder when the view has focus. Maybe we can work around this with explicit traversal handling in PartPane or the presentations mechanism. This would also allow us to cycle between editors using Ctrl+Tab. 2. When a tab is selected, the corresponding part is activated, giving it focus. This is a bug. This should only be done if the tab is clicked on, not when using keyboard. Can this be accomplished with the NO_FOCUS style? Otherwise we'll need to do it ourselves via mouse listeners (yuck). 3. Text editors eat Tab and Shift+Tab. Use Ctrl+Tab and Ctrl+Shift+Tab instead.
1a. Worth trying explicit traversal handling for Ctrl+PgUp/Ctrl+PgDown. The fact that there is no keyboard way to reliably switch pages in a view or editor tab folder is a bit strange, even though there is a hotkey way to globally cycle to another view/editor from the current page. 1b. Not sure what you mean by using Ctrl+Tab to cycle through editors - would be nice (and consistent with everybody else, and with what JAWS thinks), but Ctrl+Tab is already stolen for tab traversal - no? I'd love to make both TabFolder and CTabFolder use Ctrl+Tab as the default key for switching pages, but then people couldn't traverse forwards out of multi-line texts in tab folders, including in any dialogs that have tab folders. Not sure how important that is... they can use Shift+Tab (in a dialog) or Ctrl+Shift+Tab (in our editors)... but I thought it was a pretty big issue. I'd be happy to go there if you think it is important. I was just complaining about it to SN the other day because when JAWS is in a tab folder it says, "To switch pages press control tab". He said "Let's just fix it", but for something like that, you need a lot of people to agree... 2. Not sure how you would use NO_FOCUS style to change activation based on whether the tab was selected by mouse or by keyboard? Also, NO_FOCUS is a 'hint' - not sure which platforms it will work on. I will try a few things in my standalone example, and also check with SN, to see if there's anything else interesting either of us can think of. 3. Oops - sorry that I didn't think to try Ctrl+Shift+Tab from inside an editor, and I didn't see where focus went with Ctrl+Tab, so I thought it went nowhere. I just needed to type a few more Ctrl+Tabs to see that focus had indeed traversed out of the editor.
Note: As per discussion with Tod, reassigned to Stefan to fix 'problem 1' as described below. Note that this is P1 for accessibility for 3.0. Details: I have addressed problems 1 and 2 from comment #15 (same in comments 17 & 18). Doing this has significantly improved the keyboard accessibility of the Views and Editors tab folders, which really helps screen reader accessibility. I may be able to do more with the screen readers by working with the folks at FS, but I think we can now say that the eclipse tab folders are accessible. Tod to decide after both fixes are in. Problem 2 (arrow keys were not useful) has been fixed in CTabFolder and released to HEAD - it will be in today's integration build. Problem 1 (Ctrl+PgUp/Ctrl+PgDown not useful) must be fixed by the UI team. I am including a snippet to show how. The relevant lines of code from the snippet are: tabContents.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { switch (e.detail) { case SWT.TRAVERSE_PAGE_NEXT: case SWT.TRAVERSE_PAGE_PREVIOUS: tabFolder.traverse(e.detail); e.detail = SWT.TRAVERSE_NONE; e.doit = true; } } }); You just have to figure out which controls are "tabContents" and "tabFolder". The best place to hook the traverse listener is on the fake child(ren) (i.e. actually sibling) of the CTabFolder(s) so that they can forward the "page next/previous" traversal to the CTabFolder. The line "e.detail = SWT.TRAVERSE_NONE" tells the fake child not to do any traversal itself, and the line "e.doit = true" says that the traversal has been handled by someone, so don't pass it to anybody else. Here is the snippet, in full. It emulates eclipse's "tabfolder has siblings that act like children" story. While it can be said that this story may have other problems in future where additional traversal types should be forwarded, for now I recommend just forwarding this one traversal (page next/previous). I also recommend checking "instanceof CTabFolder" before forwarding (i.e. be very specific). Forwarding other traversals should be done carefully on an as- needed basis. import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.custom.*; public class EclipseCTabFolderAccessibilityTest { static Display display; static Shell shell; static CTabFolder tabFolder; static boolean sibling = true; // whether tab content is child or sibling of tab folder static Point maxSize; static Composite selectedContents; public static void main(String[] args) { display = new Display(); shell = new Shell(display); if (!sibling) shell.setLayout(new GridLayout()); shell.setText("Eclipse CTabFolder Accessibility Test"); maxSize = new Point(0, 0); tabFolder = new CTabFolder(shell, SWT.BORDER); for (int tabNumber = 0; tabNumber < 5; tabNumber++) { CTabItem item = new CTabItem(tabFolder, SWT.NULL); item.setText("CTab &" + tabNumber); Composite tabContents = new Composite(sibling ? (Composite) shell : (Composite) tabFolder, SWT.NONE); tabContents.setLayout(new GridLayout()); createTabContents(tabContents, tabNumber); if (sibling) { tabContents.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { switch (e.detail) { case SWT.TRAVERSE_PAGE_NEXT: case SWT.TRAVERSE_PAGE_PREVIOUS: tabFolder.traverse(e.detail); e.detail = SWT.TRAVERSE_NONE; e.doit = true; } } }); tabContents.pack(); Point size = tabContents.getSize(); if (size.x > maxSize.x || size.y > maxSize.y) maxSize = size; tabContents.setVisible(false); item.setData(tabContents); } else { item.setControl(tabContents); } } tabFolder.moveBelow(null); if (sibling) { tabFolder.setSize(tabFolder.computeSize(maxSize.x, maxSize.y)); shell.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { tabFolder.setBounds(shell.getClientArea ()); CTabItem item = tabFolder.getSelection (); if (item == null) return; setItemBounds(item); } }); tabFolder.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { showItem((CTabItem) e.item); } }); } else { new Button(shell, SWT.PUSH).setText("Hello"); } shell.pack(); shell.open(); tabFolder.setSelection(0); if (sibling) showItem(tabFolder.getItem(0)); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } static void setItemBounds(CTabItem item) { Composite tabContents = (Composite) item.getData(); tabContents.setBounds(tabFolder.getClientArea()); } static void showItem(CTabItem item) { Composite tabContents = (Composite) item.getData(); tabContents.setBounds(tabFolder.getClientArea()); if (selectedContents != null) selectedContents.setVisible (false); tabContents.setVisible(true); selectedContents = tabContents; tabContents.setFocus(); } static void createTabContents(Composite tabContents, int tabNumber) { Label itemLabel = new Label(tabContents, SWT.NONE); itemLabel.setText("Label for CTabItem " + tabNumber + " is a child of a composite"); switch (tabNumber) { case 0: Text itemText = new Text(tabContents, SWT.MULTI | SWT.BORDER); itemText.setLayoutData(new GridData (GridData.FILL_BOTH)); itemText.setText("\nText for CTabItem " + tabNumber + "\n\n\n"); break; case 1: Button itemCheck = new Button(tabContents, SWT.CHECK); itemCheck.setLayoutData(new GridData (GridData.FILL_HORIZONTAL)); itemCheck.setText("Checkbox for CTabItem " + tabNumber); break; case 2: Tree itemTree = new Tree(tabContents, SWT.SINGLE); itemTree.setLayoutData(new GridData (GridData.FILL_BOTH)); for (int i = 0; i < 4; i++) { TreeItem treeItem = new TreeItem (itemTree, SWT.NULL); treeItem.setText ("TreeItem " + i + " for CTabItem " + tabNumber); for (int j = 0; j < 3; j++) { new TreeItem(treeItem, SWT.NONE).setText("TreeItem " + i + j + " for CTabItem " + tabNumber); } } break; case 3: Table itemTable = new Table(tabContents, SWT.SINGLE); itemTable.setLayoutData(new GridData (GridData.FILL_BOTH)); itemTable.setHeaderVisible(true); itemTable.setLinesVisible(true); for (int col = 0; col < 2; col++) { TableColumn column = new TableColumn (itemTable, SWT.NONE); column.setText("Column " + col); } for (int i = 0; i < 4; i++) { TableItem tableItem = new TableItem (itemTable, SWT.NULL); tableItem.setText (new String [] {"TableItem " + i, "for CTabItem " + tabNumber}); } for (int col = 0; col < 2; col++) { itemTable.getColumn(col).pack(); } break; case 4: ToolBar itemToolBar = new ToolBar(tabContents, SWT.FLAT); itemToolBar.setLayoutData(new GridData (GridData.FILL_HORIZONTAL)); String[] toolBarFileNames = new String [] {"save", "saveas", "printer", "debug", "run", "search", "opentype"}; for (int tool = 0; tool < toolBarFileNames.length; tool++) { String fileName = toolBarFileNames [tool]; ToolItem item = new ToolItem(itemToolBar, SWT.PUSH); item.setImage(createToolBarIcon(display, fileName)); item.setToolTipText(fileName + " ToolItem for CTabItem " + tabNumber); } break; } } static Image createToolBarIcon(Display display, String fileName) { try { ImageData source = new ImageData (AccessibleToolBarTest.class.getResourceAsStream(fileName + ".gif")); ImageData mask = source.getTransparencyMask(); return new Image(display, source, mask); } catch (Exception e) { } return null; } }
The P1 part of this problem report (the regression with arrow keys in the tabs is fixed). The part assigned to Stefan is an enhancement but it would be new for 3.0. It would likely be better to create a new Bug for this enhancement and close this as fixed. I have verified this in 20040327
Closing this bug. The "enhancement" has been spun off into new bug 60489.