Skip to content

Fix window point conversion functions not exposing failure#9269

Merged
michaelDCurran merged 24 commits into
nvaccess:masterfrom
BabbageCom:fixConversionFunctions
Jan 13, 2020
Merged

Fix window point conversion functions not exposing failure#9269
michaelDCurran merged 24 commits into
nvaccess:masterfrom
BabbageCom:fixConversionFunctions

Conversation

@LeonarddeR

@LeonarddeR LeonarddeR commented Feb 13, 2019

Copy link
Copy Markdown
Collaborator

Link to issue number:

None

Summary of the issue:

There are 4 functions wrappers related to screen, client, logical and physical coordinate conversions.

  • windowUtils.logicalToPhysicalPoint
  • windowUtils.physicalToLogicalPoint
  • winUser.ClientToScreen
  • winUser.ScreenToClient

These functions take a window handle and a point structure and return 1 on success and 0 on failure. The user32 functions also set the last error when the functions fail. The point in the structure is used to calculate a new point, and on success, the coordinates in the structure are replaced. On failure, the coordinates stay the same.

However, the wrappers of these functions silently return whatever is in the structure, thereby silently ignoring whether the underlying function succeeded or failed.
As far as I've seen, for the user32 functions this is only a problem when giving it a wrong window handle. Converting coordinates falling out of the client area of the window works just fine. However, for physicalToLogicalPoint and logicalToPhysicalPoint, the functions also fail when the given coordinates fall outside the window. While normally, providing the wrong coordinates to these functions should not happen, not being able to see whether the underlying function succeeded or failed is problematic for debugging reasons.

Description of how this pull request fixes the issue:

  1. The winUser wrappers will now raise a WindowsError on failure. Note that this does not occur when providing it coordinates that fall outside the client window.
  2. the windowUtils functions raise a RuntimeError. Unfortunately, when these functions fail, they do not set the last error, so there's no way to see why the function failed.
  3. The corresponding calls in locationHelper do not catch errors, so calling screenToClient on a point or rectangle will raise a WindowsError on failure, etc.
  4. Places that call the mentioned functions, particularly displayModel, will now properly catch errors and log them.
  5. It removes Windows XP code from windowUtils

Testing performed:

This is pretty hard to test. I stumbled upon this bug when testing the highlighter in the vision framework (#9064) as that converts physical to logical rectangle coordinates. It silently seemed to fail the conversion of the top left coordinates where it succeeded in converting the bottom right coordinates, resulting in a malformed rectangle.

Known issues with pull request:

None

Change log entry:

  • Changes for developers
    • The following functions now raise an exception on failure instead of a silent return: (Fix window point conversion functions not exposing failure #9269)
      • RuntimeError: windowUtils.logicalToPhysicalPoint and windowUtils.physicalToLogicalPoint
      • WindowsError: winUser.ClientToScreen and winUser.ScreenToClient
      • Note that the wrapper methods in the locationHelper module will now also raise these exceptions on failure.

@michaelDCurran michaelDCurran left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some places you are catching exceptions and logging a debugWarning, but then it seems you're still going on and using the values you could not get. You'd either need to return some kind of safe value from the function or raise the original exception again.

Comment thread source/displayModel.py Outdated
try:
right,bottom=windowUtils.physicalToLogicalPoint(self.obj.windowHandle,right,bottom)
except RuntimeError:
log.debugWarning("physicalToLogicalPoint failed for bottom right", exc_info=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not this return from the function? if there is a runtimeError, then some of left,,top,right or button are going to not exist or be wrong...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this one. Returning from the function results in no text being returned at all. I guess your opinion is that it might be better to return no text at all rather than the wrong text. That makes sense, but then we really need to log something on the error level.

Comment thread source/NVDAObjects/window/__init__.py Outdated
Comment thread source/NVDAObjects/window/__init__.py Outdated
@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@feerrenrut: This pull requests changes the behavior of some winUser and windowUtils helper functions. Therefore looking at this to be merged into 2019.3 might be a good idea, since it introduces backwards incompatible changes (i.e. these functions now raise exceptions where they didn't before).

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@michaelDCurran: I'd like to bring this under your attention again, as this introduces backwards incompatible changes for add-ons using these functions.

@AppVeyorBot

Copy link
Copy Markdown

PR introduces Flake8 errors 😲

See test results for Failed build of commit eb06de5eb2

winUser.RECT(left, top, left + width, top + height), None,
winUser.RDW_INVALIDATE | winUser.RDW_UPDATENOW)
# Conversion to client coordinates may fail if the window handle of this object is incorrect.
# This will most likely be caused by a died window.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

died -> dead

Comment thread source/displayModel.py
wcharToInt(next(cpBufIt)),
wcharToInt(next(cpBufIt))
)
if right < left:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know under what circumstances this becomes reversed? can you put a comment here explaining this at least?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure, but my theory is that this happens in case of left to right languages.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking more about this, I think it would be better to split this specific fix out into a new pr.

@LeonarddeR LeonarddeR added the BabbageWork Pull requests filed on behalf of Babbage B.V. label Oct 8, 2019
@feerrenrut feerrenrut added this to the 2019.3 milestone Oct 14, 2019
@michaelDCurran

Copy link
Copy Markdown
Member

this pr has conflicts now.

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

Fixed now.

@dpy013

dpy013 commented Nov 19, 2019

Copy link
Copy Markdown
Contributor

hi
Is the current pr ready to merge?
thanks

@michaelDCurran

Copy link
Copy Markdown
Member

Sorry, conflicts again.

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

Conflict is now fixed.

@dpy013

dpy013 commented Nov 29, 2019

Copy link
Copy Markdown
Contributor

hi
Currently this is the last open pr for milestone 2019.3

@michaelDCurran michaelDCurran modified the milestones: 2019.3, 2020.1 Jan 13, 2020
@michaelDCurran

Copy link
Copy Markdown
Member

Moved this to the 2020.1 milestone. Needs a lot of testing.

@michaelDCurran michaelDCurran merged commit 669ae5a into nvaccess:master Jan 13, 2020
@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

Note that this pr now causes errors like this:

Traceback (most recent call last):
  File "locationHelper.pyc", line 258, in toLogical
  File "locationHelper.pyc", line 170, in toLogical
  File "windowUtils.pyc", line 93, in physicalToLogicalPoint
RuntimeError: Couldn't convert point(x=8, y=1071) from physical to logical coordinates for window 1179716

This is no mistake in this pr, rather, it is exactly proving the point that this pr was necessary. Effort should be put into finding out why these errors occur in order to fix them properly.

@lukaszgo1

Copy link
Copy Markdown
Contributor

This pr seems to be causing a few issues namely #10751 and #10704. In addition it makes working with autocomplete in Notepad++ quite inefficient, as more often than not conversion of coordinates fails for autocomplete items resulting in constant error sound while typing.
@LeonarddeR Are you planning to work further on this? If not, and no one else does it is not ready to be included in 2022.1 in the current state in my opinion.

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

Yes, I agree this needs a revert in order for it to be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BabbageWork Pull requests filed on behalf of Babbage B.V.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants