Repository: nvaccess/nvda

Issue:
Firefox: can't read text right after inline element using the mouse
<!--
Please thoroughly read NVDA's wiki article on how to fill in this template, including how to provide the required files.
Issues may be closed if the required information is not present.
https://github.com/nvaccess/nvda/wiki/Github-issue-template-explanation-and-examples
-->

### Steps to reproduce:

1. Open the provided webpage in Firefox,
2. Hover the mouse over the different lines.

### Actual behavior:

If a paragraph contains an inline element (such as a link, an image, a button, etc...) that is not placed at the start, NVDA will not be able to report the text directly following the element. But, if the paragraph is long enough, then you will be able to read the desired text (providing that you place the cursor away from the element). As you can see from my test case, this offset seems to depend on the amount of text placed before the element.

### Expected behavior:

NVDA should be able to read the text that is adjacent to an inline element, without any margin (like in Microsoft Edge or Google Chrome for instance).

### System configuration
#### NVDA installed/portable/running from source:

NVDA is installed.

#### NVDA version:

NVDA 2018.4.1

#### Windows version:

Windows 10 Education, version 1809

#### Name and version of other software in use when reproducing the issue:

Mozilla Firefox 65.0 (x64)
[bug.zip](https://github.com/nvaccess/nvda/files/2825827/bug.zip)


### Other questions
#### Does the issue still occur after restarting your PC?

Yes

#### Have you tried any other versions of NVDA?

As far back as I can remember, this problem has been there for a very long time.


Discussion:
What text unit resolution are you using? I set mine to paragraph.

I tested this in chrome and firefox, both seem flaky, and chrome is worse. Interestingly, in Firefox, the point where each line was read (after the link) seemed to match the number of characters before the link. It would be interesting to investigate this a little more to see if this is reproducible, and meaningful.
Also worth testing: The behaviour with windows at different scaling levels.
Hello @feerrenrut,
I also use paragraph as the text unit resolution, but I tried with line, on both 100% and 125% DPI factors and got the same results.
@DataTriny how is the behavior in NVDA 2020 Beta 1 and Firefox 75?
Hi @Adriani90, using the webpage I provided in the issue description, the behavior is still the same with NVDA 2020.1 beta1.
This bug goes all the way back to April 2009, ebb7dbb26b8ffb5d3e041dc40204c7b57a528981. It's also being discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=1822340#c16.

I'll submit a pull request shortly. 

Resolving patch:
diff --git a/source/NVDAObjects/IAccessible/__init__.py b/source/NVDAObjects/IAccessible/__init__.py
--- a/source/NVDAObjects/IAccessible/__init__.py
+++ b/source/NVDAObjects/IAccessible/__init__.py
@@ -198,22 +198,32 @@ def _get_unit_mouseChunk(self):
 	def expand(self,unit):
 		if unit==self.unit_mouseChunk:
 			isMouseChunkUnit=True
-			oldStart=self._startOffset
-			oldEnd=self._endOffset
+			origin = self._startOffset
 			unit=super(IA2TextTextInfo,self).unit_mouseChunk
 		else:
 			isMouseChunkUnit=False
 		super(IA2TextTextInfo,self).expand(unit)
 		if isMouseChunkUnit:
+			# If there are embedded object characters near our origin, shrink the range
+			# so that it only covers the text between them. Note that the user can
+			# mouse over the embedded objects separately. For example, if we have:
+			# before link after
+			# where "before" and "after" are plain text and "link" is a link, mousing
+			# over "before" would just read "before", mousing over "link" would read
+			# "link" and mousing over "after" would just read "after".
 			text=self._getTextRange(self._startOffset,self._endOffset)
 			if not text:
 				return
+			# Make our origin relative to the start of the text we just retrieved.
+			relativeOrigin = origin - self._startOffset
 			try:
-				self._startOffset = text.rindex(textUtils.OBJ_REPLACEMENT_CHAR, 0, oldStart - self._startOffset)
+				# Shrink the start to the nearest embedded object before our origin.
+				self._startOffset = text.rindex(textUtils.OBJ_REPLACEMENT_CHAR, 0, relativeOrigin)
 			except ValueError:
 				pass
 			try:
-				self._endOffset = text.index(textUtils.OBJ_REPLACEMENT_CHAR, oldEnd - self._startOffset)
+				# Shrink the end to the nearest embedded object after our origin.
+				self._endOffset = text.index(textUtils.OBJ_REPLACEMENT_CHAR, relativeOrigin)
 			except ValueError:
 				pass
 


Test patch: