-
-
Notifications
You must be signed in to change notification settings - Fork 650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow the review cursor to be bounded to onscreen text #9735
Conversation
…nd the console by default to maintain previous behavior.
Are you aware of how first visible oand last visible offsets are implemented in textInfos.offsets? Given your initial description, I really like this new approach, but it makes sense to implement this for offsets textInfos as well. Note that you can utilize locationHelper to implement an abstract version of |
@LeonarddeR I've added a basic implementation for |
source/NVDAObjects/__init__.py
Outdated
category=_(u"Text review"), | ||
# Translators: A gesture description. | ||
description=_(u"Toggles whether review is constrained to the currently visible text")) | ||
def script_toggleReviewBounds(self, gesture): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It worries me that this is is on the object instead of a global command. Is there a particular reason for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I too think this could be cleaner as a global command, but the reviewBounded
variable is also on the object so keeping this there might be better from an organizational standpoint...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question is whether we really believe that review Bounded should be on the object or on the textInfo, or even global. If an object gets destroyed and created again, the state of review Bounded is lost. Having review bounds on tree interceptors also makes sense, i.e. when you want to review with document review what is on screen on a particular page.
I also think that it doesn't make much sense to have review bounds doing anything when in screen review. So in that case, the command should just do nothing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it may have been my idea to put this on the object. but @LeonarddeR brings up a good point in that the state will be lost if moving away from the object and back again. The problem with having it global though is that different controls work best when reviewBounded is set in a specific way by default. I.e. consoles probably want it on by default.
Would we be comfortable having bounded on by default globally? I think this could work, but it would be a bit of a change to NvDA's behaviour. Probably a good change though. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, having this as a global default makes sense to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I also think a global default would be a plus.
It does not make much sense for a "screen" review to easily review what's not on screen.
It can be helpful at times, but is most often confusing when collaborating with a sighted person.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has now been made a global default.
Co-Authored-By: Leonard de Ruijter <leonardder@users.noreply.github.com>
source/NVDAObjects/__init__.py
Outdated
category=_(u"Text review"), | ||
# Translators: A gesture description. | ||
description=_(u"Toggles whether review is constrained to the currently visible text")) | ||
def script_toggleReviewBounds(self, gesture): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it may have been my idea to put this on the object. but @LeonarddeR brings up a good point in that the state will be lost if moving away from the object and back again. The problem with having it global though is that different controls work best when reviewBounded is set in a specific way by default. I.e. consoles probably want it on by default.
Would we be comfortable having bounded on by default globally? I think this could work, but it would be a bit of a change to NvDA's behaviour. Probably a good change though. Thoughts?
source/NVDAObjects/__init__.py
Outdated
description=_(u"Toggles whether review is constrained to the currently visible text")) | ||
def script_toggleReviewBounds(self, gesture): | ||
try: | ||
rp = api.getReviewPosition() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line should be moved above the try block. Only isOffscreen is expected to throw NotImplementedError.
source/NVDAObjects/__init__.py
Outdated
) | ||
if outOfBounds: | ||
api.setReviewPosition( | ||
self.makeTextInfo(textInfos.POSITION_CARET), isCaret=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why isCaret=True is necessary here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the textInfo
is a caret instance? Maybe it isn't needed...
source/NVDAObjects/UIA/__init__.py
Outdated
try: | ||
visiRanges = self.obj.UIATextPattern.GetVisibleRanges() | ||
element = 0 if position == textInfos.POSITION_FIRSTVISIBLE else visiRanges.length - 1 | ||
self._rangeObj = visiRanges.GetElement(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This call should use element, not 0 I think.
source/NVDAObjects/UIA/__init__.py
Outdated
element = 0 if position == textInfos.POSITION_FIRSTVISIBLE else visiRanges.length - 1 | ||
self._rangeObj = visiRanges.GetElement(0) | ||
except COMError: | ||
# Error: FIRST_VISIBLE position not supported by the UIA text pattern. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment should reflect it is first or last position not supported, not just first.
source/NVDAObjects/UIA/__init__.py
Outdated
UIAHandler.TextPatternRangeEndpoint_End) >= 0 | ||
else: | ||
# Review bounds not available. | ||
return super(UIATextInfo, self).isOutOfBounds() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is supposed to be super's isOffscreen
source/NVDAObjects/UIA/__init__.py
Outdated
@@ -702,6 +710,22 @@ def compareEndPoints(self,other,which): | |||
target=UIAHandler.TextPatternRangeEndpoint_End | |||
return self._rangeObj.CompareEndpoints(src,other._rangeObj,target) | |||
|
|||
def isOffscreen(self): | |||
visiRanges = self.obj.UIATextPattern.GetVisibleRanges() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Catch COMError around this call, raising NotImplementedError if so.
@@ -972,8 +929,21 @@ def script_review_activate(self,gesture): | |||
script_review_activate.__doc__=_("Performs the default action on the current navigator object (example: presses it if it is a button).") | |||
script_review_activate.category=SCRCAT_OBJECTNAVIGATION | |||
|
|||
def _moveWithBoundsChecking(self, info, unit, direction, endPoint=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could probably be moved into the base TextInfo class.
Also, is there a reason why this is non-distructive (I.e. returns a copy)? I don't think you actually ever make use of this. It could just do it distructively and return res like the other move... unless you have a particular plan for this not yet done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a generalization of the console's old bounds checking code (i.e. we captured an oldRange
and didn't update the underlying UIA text range if a move was impossible). Would destructive be okay here?
"@param isCaret: Whether the review position is changed due to caret
following.".
I don't think you need it. This should only be true if the
setReviewPosition call is directly caused by the caret moving.
|
Unless I've missed a call when reviewing, It looks like
_moveWithBoundsChecking only ever directly replaces a call to info.move,
and always overrides info.
|
Yes, we can do this, because the original |
@michaelDCurran @LeonarddeR This PR now uses unique IDs for NVDA objects to persist review bounds states when objects are regenerated. I'd like to move the logic that sets I'd also like to move |
NVDAObject overlay classes don't support the standard |
Currently TextContainerObject does not inherit from ScriptableObject and therefore scripts are not picked up if placed on this class.
To
|
@michaelDCurran Working now, thanks! |
@@ -551,6 +553,15 @@ def getMathMl(self, field): | |||
""" | |||
raise NotImplementedError | |||
|
|||
def _get_isOffscreen(self): | |||
""" | |||
Returns True if this textInfo is positioned outside its object's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the text is partially visible, what is returned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on the underlying implementation.
…ls and disable the console bounds checking code when oldRange is also offscreen.
Superseded for now by #9957, but I'm willing to look into this again if there's a use case. |
…e checks (PR #9957) Builds on #9614 Supersedes #9735 and #9899 Closes #9891 Previously, after the console window was maximized (or the review cursor is otherwise placed outside the visible text), text review is no longer functional. The review top line and review bottom line scripts do not function as intended. This commit changes: - The isOffscreen property has been implemented as UIAUtils.isTextRangeOffscreen. - When checking if the text range is out of bounds, we now also check that oldRange is in bounds before stopping movement. - Re-implemented POSITION_FIRST and POSITION_LAST in terms of visible ranges.
…ls and disable the console bounds checking code when oldRange is also offscreen.
This reverts commit 9fbd6b4.
Link to issue number:
Builds on #9614. Supersedes #9687 and #9899. Closes #9891.
Summary of the issue:
Currently:
Description of how this pull request fixes the issue:
This PR adds new functionality to
textInfo
objects: anisOffscreen
property andPOSITION_FIRSTVISIBLE
andPOSITION_LASTVISIBLE
position constants. A new script (bound to NVDA+o by default) toggles review bounds. Review is bounded by default where supported. An implementation of review bounds has been provided for UIA (primarily intended for use in the console) andoffsetsTextInfo
.Testing performed:
Attempted to review text before and after running
git log
in the UIA console using bounded and unbounded modes on Windows 10 1903. Verified that when review is bounded, reviewing the top/bottom lines (shift+numpad 7/9) works as intended.Known issues with pull request:
Change log entry:
== New Features ==
== Changes for Developers ==
textInfo
objects by implementing the newisOffscreen
property andPOSITION_FIRSTVISIBLE
andPOSITION_LASTVISIBLE
positions. Refer to the implementations inUIATextInfo
andoffsetsTextInfo
. (Allow the review cursor to be bounded to onscreen text #9735)scriptCategories
module. These constants are also available inglobalCommands
andinputCore
as before to avoid breaking existing code. (Allow the review cursor to be bounded to onscreen text #9735)