Skip to content
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

Provide a locationHelper module for code related to locations, rectangles and points #7537

Merged
merged 36 commits into from
Jul 30, 2018
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3ad47de
* Created a new locationHelper module
Aug 24, 2017
9d84968
Merge remote-tracking branch 'origin/master' into locationHelper
Sep 23, 2017
fb646bd
Use isinstance instead of type(self) is cls
Sep 23, 2017
8de022d
Review actions
Sep 25, 2017
b9d0bac
Merge remote-tracking branch 'origin/master' into locationHelper
Jan 6, 2018
b9c04c5
Class renames
Jan 6, 2018
1aaa5c0
Fix __radd__ operator function for Points
Jan 8, 2018
e3f8f3a
Added unit test for rect center
Jan 8, 2018
7308287
Rename rectangle operators, remove the sub operator as it does not ma…
Jan 8, 2018
070bb36
Rename Point operators
Jan 8, 2018
c2e29fd
Added many more tests, fixed operator overload (__neq__ should be __n…
Jan 9, 2018
2c9ef24
More unit tests for ctypes, fix __rsub__ for Points
Jan 9, 2018
3dbfc75
Fix for getting a center point for a rectangle, including proper roun…
Jan 9, 2018
81d3f98
Last edge case tests
Jan 9, 2018
0ba335a
Another implementation for subset and superset, doc string for collec…
Jan 10, 2018
e49888c
Remove wx.Rect from supported classes
Jan 10, 2018
c6d147f
Raise ValueError when left>right and top>bottom for RectLTRB
Apr 3, 2018
62c380e
Merge remote-tracking branch 'origin/master' into locationHelper
Apr 3, 2018
7f2cb6f
Add additional tests, improve code style for tests
Apr 3, 2018
c7f792d
Merge remote-tracking branch 'origin/master' into locationHelper
May 15, 2018
4487aa7
Remove locationHelper implementation from sysListView32
May 15, 2018
7e94522
Syslistview32: validate the rectangle before creating a RectLTWH inst…
Jun 7, 2018
3d351f2
Review actions
Jun 7, 2018
25896ba
Fix mistake in toRectLTRB function
Jun 14, 2018
dfc7e0d
Merge remote-tracking branch 'origin/master' into locationHelper
Jun 14, 2018
e407922
Review actions for SysListView32
Jun 25, 2018
3679aac
When a rectangle is created from only one point, make its width and h…
Jul 2, 2018
d456b2e
Merge remote-tracking branch 'origin/master' into locationHelper
Jul 2, 2018
80de132
Add fromNonInts factory function
Jul 5, 2018
4b4adf3
Use fromNonInts factory function for UIA locations, which are floats
Jul 5, 2018
7a05387
Refactoring
Jul 5, 2018
6c99d8c
Merge remote-tracking branch 'origin/master' into locationHelper
Jul 18, 2018
8e808ec
Merge remote-tracking branch 'origin/master' into locationHelper
Jul 23, 2018
5dfca2f
Add expandOrShrink helper method to rectangles, useful for focus high…
Jul 23, 2018
5d4ec65
Merge remote-tracking branch 'origin/master' into locationHelper
Jul 27, 2018
f055c9c
Review actions
Jul 30, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions source/NVDAObjects/IAccessible/MSHTML.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from .. import InvalidNVDAObject
from ..window import Window
from NVDAObjects.UIA import UIA, UIATextInfo
from locationHelper import RectLTRB

IID_IHTMLElement=comtypes.GUID('{3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}')

Expand Down Expand Up @@ -589,11 +590,7 @@ def _get_location(self):
top=int(r.top*yFactor)
right=int(r.right*xFactor)
bottom=int(r.bottom*yFactor)
width=right-left
height=bottom-top
p=ctypes.wintypes.POINT(x=left,y=top)
ctypes.windll.user32.ClientToScreen(self.windowHandle,ctypes.byref(p))
return (p.x,p.y,width,height)
return RectLTRB(left,top,right,bottom).toScreen(self.windowHandle).toLTWH()
return None

def _get_TextInfo(self):
Expand Down
3 changes: 2 additions & 1 deletion source/NVDAObjects/IAccessible/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import NVDAObjects.JAB
import eventHandler
from NVDAObjects.behaviors import ProgressBar, Dialog, EditableTextWithAutoSelectDetection, FocusableUnfocusableContainer, ToolTip, Notification
from locationHelper import RectLTWH

def getNVDAObjectFromEvent(hwnd,objectID,childID):
try:
Expand Down Expand Up @@ -902,7 +903,7 @@ def _get_childCount(self):

def _get_location(self):
try:
return self.IAccessibleObject.accLocation(self.IAccessibleChildID)
return RectLTWH(*self.IAccessibleObject.accLocation(self.IAccessibleChildID))
except COMError:
return None

Expand Down
27 changes: 22 additions & 5 deletions source/NVDAObjects/IAccessible/sysListView32.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
import api
import eventHandler
import winKernel
import winUser
from . import IAccessible, List
from ..window import Window
import watchdog
from NVDAObjects.behaviors import RowWithoutCellObjects, RowWithFakeNavigation
import config
from locationHelper import RectLTRB

#Window messages
LVM_FIRST=0x1000
Expand Down Expand Up @@ -53,6 +53,15 @@
LVIF_GROUPID=0x100
LVIF_COLUMNS=0x200

#GETSUBITEMRECT flags
# Returns the bounding rectangle of the entire item, including the icon and label
LVIR_BOUNDS = 0
# Returns the bounding rectangle of the icon or small icon.
LVIR_ICON = 1
# Returns the bounding rectangle of the entire item, including the icon and label.
# This is identical to LVIR_BOUNDS.
LVIR_LABEL = 2

#Item states
LVIS_FOCUSED=0x01
LVIS_SELECTED=0x02
Expand Down Expand Up @@ -298,17 +307,25 @@ class ListItem(RowWithFakeNavigation, RowWithoutCellObjects, ListItemWithoutColu

def _getColumnLocationRaw(self,index):
processHandle=self.processHandle
localRect=RECT(left=2,top=index)
# LVM_GETSUBITEMRECT requires a pointer to a RECT structure that will receive the subitem bounding rectangle information.
localRect=RECT(
left=LVIR_LABEL, # Returns the bounding rectangle of the entire item, including the icon and label
top=index # The one-based index of the subitem
Copy link
Contributor

Choose a reason for hiding this comment

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

Considering this is expecting a one-based index, I think this function should assert that index > 0

)
internalRect=winKernel.virtualAllocEx(processHandle,None,sizeof(localRect),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE)
try:
winKernel.writeProcessMemory(processHandle,internalRect,byref(localRect),sizeof(localRect),None)
watchdog.cancellableSendMessage(self.windowHandle,LVM_GETSUBITEMRECT, (self.IAccessibleChildID-1), internalRect)
winKernel.readProcessMemory(processHandle,internalRect,byref(localRect),sizeof(localRect),None)
finally:
winKernel.virtualFreeEx(processHandle,internalRect,0,winKernel.MEM_RELEASE)
windll.user32.ClientToScreen(self.windowHandle,byref(localRect))
windll.user32.ClientToScreen(self.windowHandle,byref(localRect,8))
return (localRect.left,localRect.top,localRect.right-localRect.left,localRect.bottom-localRect.top)
# ##8268: this might be a malformed rectangle
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: Too many hash symbols here.

# (i.e. with a left coordinate that is greather than the right coordinate).
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm concerned that this might happen in other cases, can we be more specific about when this is the case? Should location helper generally handle this case? If not, I would like to see that it detects it and alerts us.

Could you add a unit test specifically for malformed rectangles?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Locationhelper detects this and raises a ValueError for RectLTRB. For RectLTWH, there is currently no detection for negative widths.

I'm afraid that we can't make sure that IAccessible or UIA will never return rectangles with negative width and/or height. May be we should no longer raise a ValueError, but log a warning instead.

left = min(localRect.left, localRect.right)
top = min(localRect.top, localRect.bottom)
right = max(localRect.left, localRect.right)
bottom = max(localRect.top, localRect.bottom)
return RectLTRB(left, top, right, bottom).toScreen(self.windowHandle).toLTWH()

def _getColumnLocation(self,column):
return self._getColumnLocationRaw(self.parent._columnOrderArray[column - 1])
Expand Down
3 changes: 2 additions & 1 deletion source/NVDAObjects/JAB/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import textInfos.offsets
from logHandler import log
from .. import InvalidNVDAObject
from locationHelper import RectLTWH

JABRolesToNVDARoles={
"alert":controlTypes.ROLE_DIALOG,
Expand Down Expand Up @@ -301,7 +302,7 @@ def _get_description(self):
return re_simpleXmlTag.sub(" ", self._JABAccContextInfo.description)

def _get_location(self):
return (self._JABAccContextInfo.x,self._JABAccContextInfo.y,self._JABAccContextInfo.width,self._JABAccContextInfo.height)
return RectLTWH(self._JABAccContextInfo.x,self._JABAccContextInfo.y,self._JABAccContextInfo.width,self._JABAccContextInfo.height)

def _get_hasFocus(self):
if controlTypes.STATE_FOCUSED in self.states:
Expand Down
3 changes: 2 additions & 1 deletion source/NVDAObjects/UIA/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from NVDAObjects.behaviors import ProgressBar, EditableTextWithoutAutoSelectDetection, Dialog, Notification, EditableTextWithSuggestions
import braille
import time
from locationHelper import RectLTWH
import ui

class UIATextInfo(textInfos.TextInfo):
Expand Down Expand Up @@ -1294,7 +1295,7 @@ def _get_location(self):
top=int(r[1])
width=int(r[2])
height=int(r[3])
return left,top,width,height
return RectLTWH(left,top,width,height)

def _get_value(self):
val=self._getUIACacheablePropertyValue(UIAHandler.UIA_RangeValueValuePropertyId,True)
Expand Down
3 changes: 2 additions & 1 deletion source/NVDAObjects/window/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from NVDAObjects import NVDAObject
from NVDAObjects.behaviors import EditableText, LiveText
import watchdog
from locationHelper import toRectLTWH

re_WindowsForms=re.compile(r'^WindowsForms[0-9]*\.(.*)\.app\..*$')
re_ATL=re.compile(r'^ATL:(.*)$')
Expand Down Expand Up @@ -192,7 +193,7 @@ def _get_windowControlID(self):
def _get_location(self):
r=ctypes.wintypes.RECT()
ctypes.windll.user32.GetWindowRect(self.windowHandle,ctypes.byref(r))
return (r.left,r.top,r.right-r.left,r.bottom-r.top)
return toRectLTWH(r)

def _get_displayText(self):
"""The text at this object's location according to the display model for this object's window."""
Expand Down
5 changes: 2 additions & 3 deletions source/appModules/powerpnt.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import controlTypes
from logHandler import log
import scriptHandler
from locationHelper import RectLTRB
from NVDAObjects.window._msOfficeChart import OfficeChart

# Window classes where PowerPoint's object model should be used
Expand Down Expand Up @@ -738,9 +739,7 @@ def _get_location(self):
top=self.documentWindow.ppObjectModel.pointsToScreenPixelsY(pointTop)
right=self.documentWindow.ppObjectModel.pointsToScreenPixelsX(pointLeft+pointWidth)
bottom=self.documentWindow.ppObjectModel.pointsToScreenPixelsY(pointTop+pointHeight)
width=right-left
height=bottom-top
return (left,top,width,height)
return RectLTRB(left,top,right,bottom).toLTWH()

def _get_ppShapeType(self):
"""Fetches and caches the type of this shape."""
Expand Down
3 changes: 2 additions & 1 deletion source/displayModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import watchdog
from logHandler import log
import windowUtils
from locationHelper import RectLTRB

def wcharToInt(c):
i=ord(c)
Expand Down Expand Up @@ -178,7 +179,7 @@ def getWindowTextInRect(bindingHandle, windowHandle, left, top, right, bottom,mi
characterLocations = []
cpBufIt = iter(cpBuf)
for cp in cpBufIt:
characterLocations.append((wcharToInt(cp), wcharToInt(next(cpBufIt)), wcharToInt(next(cpBufIt)), wcharToInt(next(cpBufIt))))
characterLocations.append(RectLTRB(wcharToInt(cp), wcharToInt(next(cpBufIt)), wcharToInt(next(cpBufIt)), wcharToInt(next(cpBufIt))))
return text, characterLocations

def getFocusRect(obj):
Expand Down
Loading