Bug 405450 - Redundant calls in Accessible class when setFocus to child control
Summary: Redundant calls in Accessible class when setFocus to child control
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.7.2   Edit
Hardware: PC Windows All
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Silenio Quarti CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2013-04-11 06:12 EDT by Qian Liang CLA
Modified: 2020-02-24 04:15 EST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Qian Liang CLA 2013-04-11 06:12:48 EDT
To support IAccesible2 API, we are trying to create Accessible object for each table cell in a custom table. For performance, we just create Accessible object as needed. The goal is not to create Accessible object for cell when there is no AT running.
When cell focus changed, we will call tableAccessible.setFocus(childID) to fire an accessibility focus change event. In such case, code in Accessible.setFocus(childID) will result in a call to getChild() which cause a cell Accessible object created even with no AT tools running. Here is the call stack:
	STableRow(STableItem).getAccessible(Accessible) line: 2776	
	STable$41.getChild(AccessibleControlEvent) line: 8718	
	Accessible.checkUniqueID(int) line: 4619	
	Accessible.childIDToOs(int) line: 4645	
	Accessible.setFocus(int) line: 1385	
	STable.fireFocusAccessibilityEvent() line: 8243	
	STable.onBodyFocusIn(Event) line: 1478	
	STable$4.handleEvent(Event) line: 804	
	EventTable.sendEvent(Event) line: 84	
	STableBody(Widget).sendEvent(Event) line: 1053	
	STableBody(Canvas).WM_SETFOCUS(int, int) line: 448	
	STableBody(Control).windowProc(int, int, int, int) line: 4598	
	Display.windowProc(int, int, int, int) line: 4972	
	OS.SetFocus(int) line: not available [native method]	

One solution to improve: in Accessible.setFocus(childID) method, check refCount first. If refCount <= 1, it means that only current application running, not AT tools available. In such case, we do not need to fire COM event any more, thus no Accessible object for child will be created. Here is the code:
org.eclipse.swt.accessibility.Accessible.java
        public void setFocus(int childID) {
		checkWidget();
		if(this.refCount>1){ // only there is AT tools running, we need to fire COM event
		    int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID);
		    if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_FOCUS hwnd=" + control.handle + " childID=" + osChildID);
		    COM.NotifyWinEvent (COM.EVENT_OBJECT_FOCUS, control.handle, COM.OBJID_CLIENT, osChildID);
		}
	}

Could you help to review above solution to the problem? Could we contribute this to Eclipse build. Thanks!
Comment 1 Carolyn MacLeod CLA 2013-04-25 13:05:24 EDT
We can't always trust that the refCount will be accurate - for example, if a screen reader crashes, then the refCount may never be decremented back down to 1.

However, there is a platform way to tell if a screen reader is running.
On Windows:
static boolean isATRunning() {
  final int SPI_GETSCREENREADER = 70;
  int [] pvParam = new int [1];
  boolean result = OS.SystemParametersInfo(SPI_GETSCREENREADER, 0, pvParam, 0);
  return result && (pvParam [0] != 0);
}

On Mac:
static boolean isATRunning() {
  NSUserDefaults defaults = NSUserDefaults.standardUserDefaults();
  defaults.addSuiteNamed (NSString.stringWith("com.apple.universalaccess"));
  defaults.synchronize();
  return defaults.integerForKey (NSString.stringWith("voiceOverOnOffKey")) != 0;
}

On GTK:
static boolean isATRunning() {
  // Currently no platform way to get this info on GTK.
  // See: https://bugzilla.gnome.org/show_bug.cgi?id=649123
  // and http://web.archiveorange.com/archive/v/D5mSCXzQOd5voBtnXOzY
  return true;
}
Comment 2 Qian Liang CLA 2013-05-20 03:42:28 EDT
Although the refCount is not always accurate, it does not matter. In most case, screen reader will not run and the refCount is always 0. We can improve performance in such situation. For screen reader crash scenario, even refCount is always 1, we just always send the focus event if the setFocus method called. It has no any bad effect.

Even we have way to know whether AT tools is running in each platform, it is not good to add such kind of code each time we call setFocus. This should not be handled by upper layer applications. Thanks!
Comment 3 Silenio Quarti CLA 2013-07-10 10:27:34 EDT
The detecting code of comment#1 is going to add uncecessary overhead when the AT is running. I believe checking the refCount is a good compromise.

Fixed

http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=7b55f42ce534817654ce74c0273c74173f0f1d6d

Note that the final fix also avoids sending other events.
Comment 4 Niraj Modi CLA 2013-12-27 10:58:42 EST
Fix for this bug has caused a regression w.r.t. functioning of JAWS screen reader, refer bug 421255 :- [Accessibility] [Regression] - JAWS does not read text from label associated with text field

The below assumption made in this bug fix does not hold true for JAWS screen reader:
"refCount <= 1, it means that only current application running, no AT tools available"

But when JAWS screen reader is running the refCount continues to be 1, so JAWS is not able to read text from label.
In order to fix issue in bug 421255, required to partially revert change done as part of this bug.
Comment 5 Niraj Modi CLA 2014-01-10 06:37:00 EST
'refCount' approach to optimize Accessible code has being reverted, since it broke the functioning of JAWS.
Re-opening this bug for further investigation.
Comment 7 Eclipse Genie CLA 2020-02-24 04:15:44 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.